Skip to content

Commit 448b6ea

Browse files
committed
Auto-config support for latest Prometheus client and simpleclient
Deprecates the support for simpleclient but ensures that it can work in conjunction with support for the latest Prometheus client auto-configuration. This involves breaking changes to update public classes to support the latest Prometheus client. Deprecated support for Prometheus simpleclient is provided in renamed classes.
1 parent f99b536 commit 448b6ea

File tree

27 files changed

+1828
-195
lines changed

27 files changed

+1828
-195
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ dependencies {
5656
optional("io.micrometer:micrometer-registry-kairos")
5757
optional("io.micrometer:micrometer-registry-new-relic")
5858
optional("io.micrometer:micrometer-registry-otlp")
59+
optional("io.micrometer:micrometer-registry-prometheus")
5960
optional("io.micrometer:micrometer-registry-prometheus-simpleclient")
6061
optional("io.micrometer:micrometer-registry-stackdriver") {
6162
exclude group: "commons-logging", module: "commons-logging"

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfiguration.java

+15-83
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,26 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
1818

19-
import java.net.MalformedURLException;
20-
import java.net.URL;
21-
import java.time.Duration;
22-
import java.util.Map;
23-
2419
import io.micrometer.core.instrument.Clock;
25-
import io.prometheus.client.CollectorRegistry;
26-
import io.prometheus.client.exemplars.DefaultExemplarSampler;
27-
import io.prometheus.client.exemplars.ExemplarSampler;
28-
import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
29-
import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
30-
import io.prometheus.client.exporter.PushGateway;
20+
import io.micrometer.prometheusmetrics.PrometheusConfig;
21+
import io.micrometer.prometheusmetrics.PrometheusMeterRegistry;
22+
import io.prometheus.metrics.model.registry.PrometheusRegistry;
3123

32-
import org.springframework.beans.factory.ObjectProvider;
3324
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
3425
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
3526
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
3627
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
3728
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
38-
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager;
39-
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
4029
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
30+
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusSimpleclientScrapeEndpoint;
4131
import org.springframework.boot.autoconfigure.AutoConfiguration;
4232
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
4333
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
4434
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
4535
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
46-
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
4736
import org.springframework.boot.context.properties.EnableConfigurationProperties;
4837
import org.springframework.context.annotation.Bean;
4938
import org.springframework.context.annotation.Configuration;
50-
import org.springframework.core.env.Environment;
51-
import org.springframework.util.StringUtils;
5239

5340
/**
5441
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
@@ -58,98 +45,43 @@
5845
* @author Jonatan Ivanov
5946
* @since 2.0.0
6047
*/
61-
@SuppressWarnings("deprecation")
6248
@AutoConfiguration(
6349
before = { CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class },
6450
after = MetricsAutoConfiguration.class)
6551
@ConditionalOnBean(Clock.class)
66-
@ConditionalOnClass(io.micrometer.prometheus.PrometheusMeterRegistry.class)
52+
@ConditionalOnClass(PrometheusMeterRegistry.class)
6753
@ConditionalOnEnabledMetricsExport("prometheus")
6854
@EnableConfigurationProperties(PrometheusProperties.class)
6955
public class PrometheusMetricsExportAutoConfiguration {
7056

7157
@Bean
7258
@ConditionalOnMissingBean
73-
public io.micrometer.prometheus.PrometheusConfig prometheusConfig(PrometheusProperties prometheusProperties) {
59+
public PrometheusConfig prometheusConfig(PrometheusProperties prometheusProperties) {
7460
return new PrometheusPropertiesConfigAdapter(prometheusProperties);
7561
}
7662

7763
@Bean
7864
@ConditionalOnMissingBean
79-
public io.micrometer.prometheus.PrometheusMeterRegistry prometheusMeterRegistry(
80-
io.micrometer.prometheus.PrometheusConfig prometheusConfig, CollectorRegistry collectorRegistry,
81-
Clock clock, ObjectProvider<ExemplarSampler> exemplarSamplerProvider) {
82-
return new io.micrometer.prometheus.PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock,
83-
exemplarSamplerProvider.getIfAvailable());
65+
public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig prometheusConfig,
66+
PrometheusRegistry prometheusRegistry, Clock clock) {
67+
return new PrometheusMeterRegistry(prometheusConfig, prometheusRegistry, clock, null);
8468
}
8569

8670
@Bean
8771
@ConditionalOnMissingBean
88-
public CollectorRegistry collectorRegistry() {
89-
return new CollectorRegistry(true);
90-
}
91-
92-
@Bean
93-
@ConditionalOnMissingBean(ExemplarSampler.class)
94-
@ConditionalOnBean(SpanContextSupplier.class)
95-
public DefaultExemplarSampler exemplarSampler(SpanContextSupplier spanContextSupplier) {
96-
return new DefaultExemplarSampler(spanContextSupplier);
72+
public PrometheusRegistry prometheusRegistry() {
73+
return new PrometheusRegistry();
9774
}
9875

9976
@Configuration(proxyBeanMethods = false)
10077
@ConditionalOnAvailableEndpoint(endpoint = PrometheusScrapeEndpoint.class)
10178
public static class PrometheusScrapeEndpointConfiguration {
10279

80+
@SuppressWarnings("removal")
10381
@Bean
104-
@ConditionalOnMissingBean
105-
public PrometheusScrapeEndpoint prometheusEndpoint(CollectorRegistry collectorRegistry) {
106-
return new PrometheusScrapeEndpoint(collectorRegistry);
107-
}
108-
109-
}
110-
111-
/**
112-
* Configuration for <a href="https://github.com/prometheus/pushgateway">Prometheus
113-
* Pushgateway</a>.
114-
*/
115-
@Configuration(proxyBeanMethods = false)
116-
@ConditionalOnClass(PushGateway.class)
117-
@ConditionalOnProperty(prefix = "management.prometheus.metrics.export.pushgateway", name = "enabled")
118-
public static class PrometheusPushGatewayConfiguration {
119-
120-
/**
121-
* The fallback job name. We use 'spring' since there's a history of Prometheus
122-
* spring integration defaulting to that name from when Prometheus integration
123-
* didn't exist in Spring itself.
124-
*/
125-
private static final String FALLBACK_JOB = "spring";
126-
127-
@Bean
128-
@ConditionalOnMissingBean
129-
public PrometheusPushGatewayManager prometheusPushGatewayManager(CollectorRegistry collectorRegistry,
130-
PrometheusProperties prometheusProperties, Environment environment) throws MalformedURLException {
131-
PrometheusProperties.Pushgateway properties = prometheusProperties.getPushgateway();
132-
Duration pushRate = properties.getPushRate();
133-
String job = getJob(properties, environment);
134-
Map<String, String> groupingKey = properties.getGroupingKey();
135-
ShutdownOperation shutdownOperation = properties.getShutdownOperation();
136-
PushGateway pushGateway = initializePushGateway(properties.getBaseUrl());
137-
if (StringUtils.hasText(properties.getUsername())) {
138-
pushGateway.setConnectionFactory(
139-
new BasicAuthHttpConnectionFactory(properties.getUsername(), properties.getPassword()));
140-
}
141-
return new PrometheusPushGatewayManager(pushGateway, collectorRegistry, pushRate, job, groupingKey,
142-
shutdownOperation);
143-
}
144-
145-
private PushGateway initializePushGateway(String url) throws MalformedURLException {
146-
return new PushGateway(new URL(url));
147-
}
148-
149-
private String getJob(PrometheusProperties.Pushgateway properties, Environment environment) {
150-
String job = properties.getJob();
151-
job = (job != null) ? job : environment.getProperty("spring.application.name");
152-
return (job != null) ? job : FALLBACK_JOB;
82+
@ConditionalOnMissingBean({ PrometheusScrapeEndpoint.class, PrometheusSimpleclientScrapeEndpoint.class })
83+
public PrometheusScrapeEndpoint prometheusEndpoint(PrometheusRegistry prometheusRegistry) {
84+
return new PrometheusScrapeEndpoint(prometheusRegistry);
15385
}
15486

15587
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
* @author Stephane Nicoll
3232
* @since 2.0.0
3333
*/
34-
@SuppressWarnings("deprecation")
3534
@ConfigurationProperties(prefix = "management.prometheus.metrics.export")
3635
public class PrometheusProperties {
3736

@@ -55,6 +54,8 @@ public class PrometheusProperties {
5554
/**
5655
* Histogram type for backing DistributionSummary and Timer.
5756
*/
57+
@SuppressWarnings("DeprecatedIsStillUsed")
58+
@Deprecated(since = "3.3.0", forRemoval = true)
5859
private io.micrometer.prometheus.HistogramFlavor histogramFlavor = io.micrometer.prometheus.HistogramFlavor.Prometheus;
5960

6061
/**
@@ -70,10 +71,12 @@ public void setDescriptions(boolean descriptions) {
7071
this.descriptions = descriptions;
7172
}
7273

74+
@SuppressWarnings("deprecation")
7375
public io.micrometer.prometheus.HistogramFlavor getHistogramFlavor() {
7476
return this.histogramFlavor;
7577
}
7678

79+
@SuppressWarnings("deprecation")
7780
public void setHistogramFlavor(io.micrometer.prometheus.HistogramFlavor histogramFlavor) {
7881
this.histogramFlavor = histogramFlavor;
7982
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java

+6-12
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818

1919
import java.time.Duration;
2020

21+
import io.micrometer.prometheusmetrics.PrometheusConfig;
22+
2123
import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PropertiesConfigAdapter;
2224

2325
/**
24-
* Adapter to convert {@link PrometheusProperties} to a
25-
* {@link io.micrometer.prometheus.PrometheusConfig}.
26+
* Adapter to convert {@link PrometheusProperties} to a {@link PrometheusConfig}.
2627
*
2728
* @author Jon Schneider
2829
* @author Phillip Webb
2930
*/
30-
@SuppressWarnings("deprecation")
3131
class PrometheusPropertiesConfigAdapter extends PropertiesConfigAdapter<PrometheusProperties>
32-
implements io.micrometer.prometheus.PrometheusConfig {
32+
implements PrometheusConfig {
3333

3434
PrometheusPropertiesConfigAdapter(PrometheusProperties properties) {
3535
super(properties);
@@ -47,18 +47,12 @@ public String get(String key) {
4747

4848
@Override
4949
public boolean descriptions() {
50-
return get(PrometheusProperties::isDescriptions, io.micrometer.prometheus.PrometheusConfig.super::descriptions);
51-
}
52-
53-
@Override
54-
public io.micrometer.prometheus.HistogramFlavor histogramFlavor() {
55-
return get(PrometheusProperties::getHistogramFlavor,
56-
io.micrometer.prometheus.PrometheusConfig.super::histogramFlavor);
50+
return get(PrometheusProperties::isDescriptions, PrometheusConfig.super::descriptions);
5751
}
5852

5953
@Override
6054
public Duration step() {
61-
return get(PrometheusProperties::getStep, io.micrometer.prometheus.PrometheusConfig.super::step);
55+
return get(PrometheusProperties::getStep, PrometheusConfig.super::step);
6256
}
6357

6458
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
18+
19+
import java.net.MalformedURLException;
20+
import java.net.URL;
21+
import java.time.Duration;
22+
import java.util.Map;
23+
24+
import io.micrometer.core.instrument.Clock;
25+
import io.micrometer.prometheus.PrometheusConfig;
26+
import io.micrometer.prometheus.PrometheusMeterRegistry;
27+
import io.prometheus.client.CollectorRegistry;
28+
import io.prometheus.client.exemplars.DefaultExemplarSampler;
29+
import io.prometheus.client.exemplars.ExemplarSampler;
30+
import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
31+
import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
32+
import io.prometheus.client.exporter.PushGateway;
33+
34+
import org.springframework.beans.factory.ObjectProvider;
35+
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
36+
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
37+
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
38+
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
39+
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
40+
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager;
41+
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
42+
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
43+
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusSimpleclientScrapeEndpoint;
44+
import org.springframework.boot.autoconfigure.AutoConfiguration;
45+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
46+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
47+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
48+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
49+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
50+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
51+
import org.springframework.context.annotation.Bean;
52+
import org.springframework.context.annotation.Configuration;
53+
import org.springframework.core.env.Environment;
54+
import org.springframework.util.StringUtils;
55+
56+
/**
57+
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus
58+
* with the Prometheus simpleclient.
59+
*
60+
* @author Jon Schneider
61+
* @author David J. M. Karlsen
62+
* @author Jonatan Ivanov
63+
* @since 2.0.0
64+
* @deprecated in favor of {@link PrometheusMetricsExportAutoConfiguration}
65+
*/
66+
@Deprecated(since = "3.3.0", forRemoval = true)
67+
@AutoConfiguration(
68+
before = { CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class },
69+
after = { MetricsAutoConfiguration.class, PrometheusMetricsExportAutoConfiguration.class })
70+
@ConditionalOnBean(Clock.class)
71+
@ConditionalOnClass(PrometheusMeterRegistry.class)
72+
@ConditionalOnEnabledMetricsExport("prometheus")
73+
@EnableConfigurationProperties(PrometheusProperties.class)
74+
public class PrometheusSimpleclientMetricsExportAutoConfiguration {
75+
76+
@Bean
77+
@ConditionalOnMissingBean
78+
public PrometheusConfig simpleclientPrometheusConfig(PrometheusProperties prometheusProperties) {
79+
return new PrometheusSimpleclientPropertiesConfigAdapter(prometheusProperties);
80+
}
81+
82+
@Bean
83+
@ConditionalOnMissingBean
84+
public io.micrometer.prometheus.PrometheusMeterRegistry simpleclientPrometheusMeterRegistry(
85+
io.micrometer.prometheus.PrometheusConfig prometheusConfig, CollectorRegistry collectorRegistry,
86+
Clock clock, ObjectProvider<ExemplarSampler> exemplarSamplerProvider) {
87+
return new io.micrometer.prometheus.PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock,
88+
exemplarSamplerProvider.getIfAvailable());
89+
}
90+
91+
@Bean
92+
@ConditionalOnMissingBean
93+
public CollectorRegistry collectorRegistry() {
94+
return new CollectorRegistry(true);
95+
}
96+
97+
@Bean
98+
@ConditionalOnMissingBean(ExemplarSampler.class)
99+
@ConditionalOnBean(SpanContextSupplier.class)
100+
public DefaultExemplarSampler exemplarSampler(SpanContextSupplier spanContextSupplier) {
101+
return new DefaultExemplarSampler(spanContextSupplier);
102+
}
103+
104+
@SuppressWarnings("removal")
105+
@Configuration(proxyBeanMethods = false)
106+
@ConditionalOnAvailableEndpoint(endpoint = PrometheusSimpleclientScrapeEndpoint.class)
107+
public static class PrometheusScrapeEndpointConfiguration {
108+
109+
@Bean
110+
@ConditionalOnMissingBean({ PrometheusSimpleclientScrapeEndpoint.class, PrometheusScrapeEndpoint.class })
111+
public PrometheusSimpleclientScrapeEndpoint prometheusEndpoint(CollectorRegistry collectorRegistry) {
112+
return new PrometheusSimpleclientScrapeEndpoint(collectorRegistry);
113+
}
114+
115+
}
116+
117+
/**
118+
* Configuration for <a href="https://github.com/prometheus/pushgateway">Prometheus
119+
* Pushgateway</a>.
120+
*/
121+
@Configuration(proxyBeanMethods = false)
122+
@ConditionalOnClass(PushGateway.class)
123+
@ConditionalOnProperty(prefix = "management.prometheus.metrics.export.pushgateway", name = "enabled")
124+
public static class PrometheusPushGatewayConfiguration {
125+
126+
/**
127+
* The fallback job name. We use 'spring' since there's a history of Prometheus
128+
* spring integration defaulting to that name from when Prometheus integration
129+
* didn't exist in Spring itself.
130+
*/
131+
private static final String FALLBACK_JOB = "spring";
132+
133+
@Bean
134+
@ConditionalOnMissingBean
135+
public PrometheusPushGatewayManager prometheusPushGatewayManager(CollectorRegistry collectorRegistry,
136+
PrometheusProperties prometheusProperties, Environment environment) throws MalformedURLException {
137+
PrometheusProperties.Pushgateway properties = prometheusProperties.getPushgateway();
138+
Duration pushRate = properties.getPushRate();
139+
String job = getJob(properties, environment);
140+
Map<String, String> groupingKey = properties.getGroupingKey();
141+
ShutdownOperation shutdownOperation = properties.getShutdownOperation();
142+
PushGateway pushGateway = initializePushGateway(properties.getBaseUrl());
143+
if (StringUtils.hasText(properties.getUsername())) {
144+
pushGateway.setConnectionFactory(
145+
new BasicAuthHttpConnectionFactory(properties.getUsername(), properties.getPassword()));
146+
}
147+
return new PrometheusPushGatewayManager(pushGateway, collectorRegistry, pushRate, job, groupingKey,
148+
shutdownOperation);
149+
}
150+
151+
private PushGateway initializePushGateway(String url) throws MalformedURLException {
152+
return new PushGateway(new URL(url));
153+
}
154+
155+
private String getJob(PrometheusProperties.Pushgateway properties, Environment environment) {
156+
String job = properties.getJob();
157+
job = (job != null) ? job : environment.getProperty("spring.application.name");
158+
return (job != null) ? job : FALLBACK_JOB;
159+
}
160+
161+
}
162+
163+
}

0 commit comments

Comments
 (0)