Skip to content

Commit 63ecfac

Browse files
committed
Support Pushgateway with new Prometheus client
Closes gh-43923
1 parent 465f05b commit 63ecfac

File tree

10 files changed

+329
-112
lines changed

10 files changed

+329
-112
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ dependencies {
5454
exclude group: "commons-logging", module: "commons-logging"
5555
exclude group: "javax.annotation", module: "javax.annotation-api"
5656
}
57-
optional("io.prometheus:simpleclient_pushgateway") {
58-
exclude group: "javax.xml.bind", module: "jaxb-api"
59-
}
6057
optional("io.micrometer:micrometer-registry-signalfx")
6158
optional("io.micrometer:micrometer-registry-statsd")
6259
optional("io.micrometer:micrometer-registry-wavefront")
@@ -65,6 +62,7 @@ dependencies {
6562
optional("io.opentelemetry:opentelemetry-exporter-zipkin")
6663
optional("io.opentelemetry:opentelemetry-exporter-otlp")
6764
optional("io.projectreactor.netty:reactor-netty-http")
65+
optional("io.prometheus:prometheus-metrics-exporter-pushgateway")
6866
optional("io.r2dbc:r2dbc-pool")
6967
optional("io.r2dbc:r2dbc-proxy")
7068
optional("io.r2dbc:r2dbc-spi")

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

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import io.micrometer.core.instrument.Clock;
2020
import io.micrometer.prometheusmetrics.PrometheusConfig;
2121
import io.micrometer.prometheusmetrics.PrometheusMeterRegistry;
22+
import io.prometheus.metrics.exporter.pushgateway.Format;
23+
import io.prometheus.metrics.exporter.pushgateway.PushGateway;
24+
import io.prometheus.metrics.exporter.pushgateway.PushGateway.Builder;
25+
import io.prometheus.metrics.exporter.pushgateway.Scheme;
2226
import io.prometheus.metrics.model.registry.PrometheusRegistry;
2327
import io.prometheus.metrics.tracer.common.SpanContext;
2428

@@ -28,15 +32,20 @@
2832
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
2933
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
3034
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
35+
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager;
3136
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
3237
import org.springframework.boot.autoconfigure.AutoConfiguration;
3338
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3439
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3540
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3641
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
42+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3743
import org.springframework.boot.context.properties.EnableConfigurationProperties;
44+
import org.springframework.boot.context.properties.source.MutuallyExclusiveConfigurationPropertiesException;
3845
import org.springframework.context.annotation.Bean;
3946
import org.springframework.context.annotation.Configuration;
47+
import org.springframework.core.env.Environment;
48+
import org.springframework.util.StringUtils;
4049

4150
/**
4251
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
@@ -87,4 +96,74 @@ PrometheusScrapeEndpoint prometheusEndpoint(PrometheusRegistry prometheusRegistr
8796

8897
}
8998

99+
/**
100+
* Configuration for <a href="https://github.com/prometheus/pushgateway">Prometheus
101+
* Pushgateway</a>.
102+
*/
103+
@Configuration(proxyBeanMethods = false)
104+
@ConditionalOnClass(PushGateway.class)
105+
@ConditionalOnProperty(prefix = "management.prometheus.metrics.export.pushgateway", name = "enabled")
106+
static class PrometheusPushGatewayConfiguration {
107+
108+
/**
109+
* The fallback job name. We use 'spring' since there's a history of Prometheus
110+
* spring integration defaulting to that name from when Prometheus integration
111+
* didn't exist in Spring itself.
112+
*/
113+
private static final String FALLBACK_JOB = "spring";
114+
115+
@Bean
116+
@ConditionalOnMissingBean
117+
PrometheusPushGatewayManager prometheusPushGatewayManager(PrometheusRegistry registry,
118+
PrometheusProperties prometheusProperties, Environment environment) {
119+
PrometheusProperties.Pushgateway properties = prometheusProperties.getPushgateway();
120+
PushGateway pushGateway = initializePushGateway(registry, properties, environment);
121+
return new PrometheusPushGatewayManager(pushGateway, properties.getPushRate(),
122+
properties.getShutdownOperation());
123+
}
124+
125+
private PushGateway initializePushGateway(PrometheusRegistry registry,
126+
PrometheusProperties.Pushgateway properties, Environment environment) {
127+
Builder builder = PushGateway.builder()
128+
.address(properties.getAddress())
129+
.scheme(scheme(properties))
130+
.format(format(properties))
131+
.job(getJob(properties, environment))
132+
.registry(registry);
133+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
134+
entries.put("management.prometheus.metrics.export.pushgateway.token", properties.getToken());
135+
entries.put("management.prometheus.metrics.export.pushgateway.username", properties.getUsername());
136+
});
137+
if (StringUtils.hasText(properties.getToken())) {
138+
builder.bearerToken(properties.getToken());
139+
}
140+
else if (StringUtils.hasText(properties.getUsername())) {
141+
builder.basicAuth(properties.getUsername(), properties.getPassword());
142+
}
143+
properties.getGroupingKey().forEach(builder::groupingKey);
144+
return builder.build();
145+
}
146+
147+
private Scheme scheme(PrometheusProperties.Pushgateway properties) {
148+
return switch (properties.getScheme()) {
149+
case HTTP -> Scheme.HTTP;
150+
case HTTPS -> Scheme.HTTPS;
151+
};
152+
}
153+
154+
private Format format(PrometheusProperties.Pushgateway properties) {
155+
return switch (properties.getFormat()) {
156+
case PROTOBUF -> Format.PROMETHEUS_PROTOBUF;
157+
case TEXT -> Format.PROMETHEUS_TEXT;
158+
};
159+
}
160+
161+
private String getJob(PrometheusProperties.Pushgateway properties, Environment environment) {
162+
String job = properties.getJob();
163+
job = (job != null) ? job : environment.getProperty("spring.application.name");
164+
return (job != null) ? job : FALLBACK_JOB;
165+
}
166+
167+
}
168+
90169
}

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

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,14 @@ public static class Pushgateway {
104104
private Boolean enabled = false;
105105

106106
/**
107-
* Base URL for the Pushgateway.
107+
* Address (host:port) for the Pushgateway.
108108
*/
109-
private String baseUrl = "http://localhost:9091";
109+
private String address = "localhost:9091";
110+
111+
/**
112+
* The scheme to use when pushing metrics.
113+
*/
114+
private Scheme scheme = Scheme.HTTP;
110115

111116
/**
112117
* Login user of the Prometheus Pushgateway.
@@ -118,6 +123,16 @@ public static class Pushgateway {
118123
*/
119124
private String password;
120125

126+
/**
127+
* The token to use for authentication with the Prometheus Pushgateway.
128+
*/
129+
private String token;
130+
131+
/**
132+
* The format to use when pushing metrics.
133+
*/
134+
private Format format = Format.PROTOBUF;
135+
121136
/**
122137
* Frequency with which to push metrics.
123138
*/
@@ -146,12 +161,12 @@ public void setEnabled(Boolean enabled) {
146161
this.enabled = enabled;
147162
}
148163

149-
public String getBaseUrl() {
150-
return this.baseUrl;
164+
public String getAddress() {
165+
return this.address;
151166
}
152167

153-
public void setBaseUrl(String baseUrl) {
154-
this.baseUrl = baseUrl;
168+
public void setAddress(String address) {
169+
this.address = address;
155170
}
156171

157172
public String getUsername() {
@@ -202,6 +217,58 @@ public void setShutdownOperation(ShutdownOperation shutdownOperation) {
202217
this.shutdownOperation = shutdownOperation;
203218
}
204219

220+
public Scheme getScheme() {
221+
return this.scheme;
222+
}
223+
224+
public void setScheme(Scheme scheme) {
225+
this.scheme = scheme;
226+
}
227+
228+
public String getToken() {
229+
return this.token;
230+
}
231+
232+
public void setToken(String token) {
233+
this.token = token;
234+
}
235+
236+
public Format getFormat() {
237+
return this.format;
238+
}
239+
240+
public void setFormat(Format format) {
241+
this.format = format;
242+
}
243+
244+
public enum Format {
245+
246+
/**
247+
* Push metrics in text format.
248+
*/
249+
TEXT,
250+
251+
/**
252+
* Push metrics in protobuf format.
253+
*/
254+
PROTOBUF
255+
256+
}
257+
258+
public enum Scheme {
259+
260+
/**
261+
* Use HTTP to push metrics.
262+
*/
263+
HTTP,
264+
265+
/**
266+
* Use HTTPS to push metrics.
267+
*/
268+
HTTPS
269+
270+
}
271+
205272
}
206273

207274
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,14 @@
20832083
"type": "java.lang.Boolean",
20842084
"description": "Whether auto-configuration of tracing is enabled to export OTLP traces."
20852085
},
2086+
{
2087+
"name": "management.promethus.metrics.export.pushgateway.base-url",
2088+
"type": "java.lang.String",
2089+
"deprecation": {
2090+
"level": "error",
2091+
"replacement": "management.prometheus.metrics.export.pushgateway.address"
2092+
}
2093+
},
20862094
{
20872095
"name": "management.server.add-application-context-header",
20882096
"type": "java.lang.Boolean",

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/PrometheusScrapeEndpointDocumentationTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
2121
import io.micrometer.core.instrument.Clock;
2222
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
2323
import io.micrometer.prometheusmetrics.PrometheusMeterRegistry;
24-
import io.prometheus.client.exporter.common.TextFormat;
24+
import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter;
2525
import io.prometheus.metrics.model.registry.PrometheusRegistry;
2626
import org.junit.jupiter.api.Test;
2727

@@ -50,7 +50,7 @@ void prometheus() {
5050

5151
@Test
5252
void prometheusOpenmetrics() {
53-
assertThat(this.mvc.get().uri("/actuator/prometheus").accept(TextFormat.CONTENT_TYPE_OPENMETRICS_100))
53+
assertThat(this.mvc.get().uri("/actuator/prometheus").accept(OpenMetricsTextFormatWriter.CONTENT_TYPE))
5454
.satisfies((result) -> {
5555
assertThat(result).hasStatusOk()
5656
.headers()

0 commit comments

Comments
 (0)