Polish "Add basic auth support for Prometheus pushgateway"
See gh-22548
This commit is contained in:
parent
9ddc97f815
commit
14eb041086
|
|
@ -16,6 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
|
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import io.micrometer.core.instrument.Clock;
|
import io.micrometer.core.instrument.Clock;
|
||||||
import io.micrometer.prometheus.PrometheusConfig;
|
import io.micrometer.prometheus.PrometheusConfig;
|
||||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||||
|
|
@ -24,6 +29,7 @@ import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
|
||||||
import io.prometheus.client.exporter.PushGateway;
|
import io.prometheus.client.exporter.PushGateway;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
|
||||||
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||||
|
|
@ -44,21 +50,17 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
|
* {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Prometheus.
|
||||||
*
|
*
|
||||||
|
* @since 2.0.0
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @author David J. M. Karlsen
|
* @author David J. M. Karlsen
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@AutoConfigureBefore({CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class})
|
@AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class })
|
||||||
@AutoConfigureAfter(MetricsAutoConfiguration.class)
|
@AutoConfigureAfter(MetricsAutoConfiguration.class)
|
||||||
@ConditionalOnBean(Clock.class)
|
@ConditionalOnBean(Clock.class)
|
||||||
@ConditionalOnClass(PrometheusMeterRegistry.class)
|
@ConditionalOnClass(PrometheusMeterRegistry.class)
|
||||||
|
|
@ -75,7 +77,7 @@ public class PrometheusMetricsExportAutoConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig prometheusConfig,
|
public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig prometheusConfig,
|
||||||
CollectorRegistry collectorRegistry, Clock clock) {
|
CollectorRegistry collectorRegistry, Clock clock) {
|
||||||
return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock);
|
return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,30 +120,30 @@ public class PrometheusMetricsExportAutoConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public PrometheusPushGatewayManager prometheusPushGatewayManager(CollectorRegistry collectorRegistry,
|
public PrometheusPushGatewayManager prometheusPushGatewayManager(CollectorRegistry collectorRegistry,
|
||||||
PrometheusProperties prometheusProperties, Environment environment) {
|
PrometheusProperties prometheusProperties, Environment environment) {
|
||||||
PrometheusProperties.Pushgateway properties = prometheusProperties.getPushgateway();
|
PrometheusProperties.Pushgateway properties = prometheusProperties.getPushgateway();
|
||||||
Duration pushRate = properties.getPushRate();
|
Duration pushRate = properties.getPushRate();
|
||||||
String job = getJob(properties, environment);
|
String job = getJob(properties, environment);
|
||||||
Map<String, String> groupingKey = properties.getGroupingKey();
|
Map<String, String> groupingKey = properties.getGroupingKey();
|
||||||
ShutdownOperation shutdownOperation = properties.getShutdownOperation();
|
ShutdownOperation shutdownOperation = properties.getShutdownOperation();
|
||||||
return new PrometheusPushGatewayManager(getPushGateway(properties.getBaseUrl()), collectorRegistry,
|
PushGateway pushGateway = initializePushGateway(properties.getBaseUrl());
|
||||||
pushRate, job, groupingKey, shutdownOperation);
|
if (StringUtils.hasText(properties.getUsername())) {
|
||||||
|
pushGateway.setConnectionFactory(
|
||||||
|
new BasicAuthHttpConnectionFactory(properties.getUsername(), properties.getPassword()));
|
||||||
|
}
|
||||||
|
return new PrometheusPushGatewayManager(pushGateway, collectorRegistry, pushRate, job, groupingKey,
|
||||||
|
shutdownOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PushGateway getPushGateway(String url) {
|
private PushGateway initializePushGateway(String url) {
|
||||||
PushGateway pushGateway = null;
|
|
||||||
try {
|
try {
|
||||||
pushGateway = new PushGateway(new URL(url));
|
return new PushGateway(new URL(url));
|
||||||
} catch (MalformedURLException ex) {
|
}
|
||||||
|
catch (MalformedURLException ex) {
|
||||||
logger.warn(LogMessage
|
logger.warn(LogMessage
|
||||||
.format("Invalid PushGateway base url '%s': update your configuration to a valid URL", url));
|
.format("Invalid PushGateway base url '%s': update your configuration to a valid URL", url));
|
||||||
pushGateway = new PushGateway(url);
|
return new PushGateway(url);
|
||||||
}
|
}
|
||||||
PrometheusProperties.Pushgateway properties = prometheusProperties.getPushgateway();
|
|
||||||
if (properties.getAuthEnabled()) {
|
|
||||||
pushgateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(properties.getAuthusername(), properties.getAuthpassword()));
|
|
||||||
}
|
|
||||||
return pushGateway;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getJob(PrometheusProperties.Pushgateway properties, Environment environment) {
|
private String getJob(PrometheusProperties.Pushgateway properties, Environment environment) {
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,15 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
|
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
|
||||||
|
|
||||||
import io.micrometer.prometheus.HistogramFlavor;
|
|
||||||
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.micrometer.prometheus.HistogramFlavor;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ConfigurationProperties @ConfigurationProperties} for configuring metrics export
|
* {@link ConfigurationProperties @ConfigurationProperties} for configuring metrics export
|
||||||
* to Prometheus.
|
* to Prometheus.
|
||||||
|
|
@ -85,7 +86,6 @@ public class PrometheusProperties {
|
||||||
return this.pushgateway;
|
return this.pushgateway;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration options for push-based interaction with Prometheus.
|
* Configuration options for push-based interaction with Prometheus.
|
||||||
*/
|
*/
|
||||||
|
|
@ -101,6 +101,16 @@ public class PrometheusProperties {
|
||||||
*/
|
*/
|
||||||
private String baseUrl = "http://localhost:9091";
|
private String baseUrl = "http://localhost:9091";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login user of the Prometheus Pushgateway.
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login password of the Prometheus Pushgateway.
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frequency with which to push metrics.
|
* Frequency with which to push metrics.
|
||||||
*/
|
*/
|
||||||
|
|
@ -116,21 +126,6 @@ public class PrometheusProperties {
|
||||||
*/
|
*/
|
||||||
private Map<String, String> groupingKey = new HashMap<>();
|
private Map<String, String> groupingKey = new HashMap<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable publishing via a Prometheus Pushgateway with Basic Auth.
|
|
||||||
*/
|
|
||||||
private Boolean authEnabled = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prometheus Pushgateway basic-auth username.
|
|
||||||
*/
|
|
||||||
private String authusername;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prometheus Pushgateway basic-auth password.
|
|
||||||
*/
|
|
||||||
private String authpassword;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation that should be performed on shutdown.
|
* Operation that should be performed on shutdown.
|
||||||
*/
|
*/
|
||||||
|
|
@ -152,6 +147,22 @@ public class PrometheusProperties {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return this.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
public Duration getPushRate() {
|
public Duration getPushRate() {
|
||||||
return this.pushRate;
|
return this.pushRate;
|
||||||
}
|
}
|
||||||
|
|
@ -184,29 +195,6 @@ public class PrometheusProperties {
|
||||||
this.shutdownOperation = shutdownOperation;
|
this.shutdownOperation = shutdownOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getAuthEnabled() {
|
|
||||||
return this.authEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthEnabled(Boolean authEnabled) {
|
|
||||||
this.authEnabled = authEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthusername() {
|
|
||||||
return authusername;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthusername(String authusername) {
|
|
||||||
this.authusername = authusername;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthpassword() {
|
|
||||||
return authpassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthpassword(String authpassword) {
|
|
||||||
this.authpassword = authpassword;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,16 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
|
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import io.micrometer.core.instrument.Clock;
|
import io.micrometer.core.instrument.Clock;
|
||||||
import io.micrometer.prometheus.PrometheusConfig;
|
import io.micrometer.prometheus.PrometheusConfig;
|
||||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||||
import io.prometheus.client.CollectorRegistry;
|
import io.prometheus.client.CollectorRegistry;
|
||||||
|
import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
|
||||||
|
import io.prometheus.client.exporter.DefaultHttpConnectionFactory;
|
||||||
|
import io.prometheus.client.exporter.HttpConnectionFactory;
|
||||||
|
import io.prometheus.client.exporter.PushGateway;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
|
@ -29,6 +35,7 @@ import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScra
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||||
import org.springframework.boot.test.system.CapturedOutput;
|
import org.springframework.boot.test.system.CapturedOutput;
|
||||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
@ -42,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Tests for {@link PrometheusMetricsExportAutoConfiguration}.
|
* Tests for {@link PrometheusMetricsExportAutoConfiguration}.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
@ExtendWith(OutputCaptureExtension.class)
|
@ExtendWith(OutputCaptureExtension.class)
|
||||||
class PrometheusMetricsExportAutoConfigurationTests {
|
class PrometheusMetricsExportAutoConfigurationTests {
|
||||||
|
|
@ -142,6 +150,15 @@ class PrometheusMetricsExportAutoConfigurationTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withPushGatewayNoBasicAuth() {
|
||||||
|
this.contextRunner.withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class))
|
||||||
|
.withPropertyValues("management.metrics.export.prometheus.pushgateway.enabled=true")
|
||||||
|
.withUserConfiguration(BaseConfiguration.class)
|
||||||
|
.run(hasHttpConnectionFactory((httpConnectionFactory) -> assertThat(httpConnectionFactory)
|
||||||
|
.isInstanceOf(DefaultHttpConnectionFactory.class)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Deprecated
|
@Deprecated
|
||||||
void withCustomLegacyPushGatewayURL(CapturedOutput output) {
|
void withCustomLegacyPushGatewayURL(CapturedOutput output) {
|
||||||
|
|
@ -163,11 +180,34 @@ class PrometheusMetricsExportAutoConfigurationTests {
|
||||||
.run((context) -> hasGatewayURL(context, "https://example.com:8080/metrics/"));
|
.run((context) -> hasGatewayURL(context, "https://example.com:8080/metrics/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withPushGatewayBasicAuth() {
|
||||||
|
this.contextRunner.withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class))
|
||||||
|
.withPropertyValues("management.metrics.export.prometheus.pushgateway.enabled=true",
|
||||||
|
"management.metrics.export.prometheus.pushgateway.username=admin",
|
||||||
|
"management.metrics.export.prometheus.pushgateway.password=secret")
|
||||||
|
.withUserConfiguration(BaseConfiguration.class)
|
||||||
|
.run(hasHttpConnectionFactory((httpConnectionFactory) -> assertThat(httpConnectionFactory)
|
||||||
|
.isInstanceOf(BasicAuthHttpConnectionFactory.class)));
|
||||||
|
}
|
||||||
|
|
||||||
private void hasGatewayURL(AssertableApplicationContext context, String url) {
|
private void hasGatewayURL(AssertableApplicationContext context, String url) {
|
||||||
|
assertThat(getPushGateway(context)).hasFieldOrPropertyWithValue("gatewayBaseURL", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContextConsumer<AssertableApplicationContext> hasHttpConnectionFactory(
|
||||||
|
Consumer<HttpConnectionFactory> httpConnectionFactory) {
|
||||||
|
return (context) -> {
|
||||||
|
PushGateway pushGateway = getPushGateway(context);
|
||||||
|
httpConnectionFactory
|
||||||
|
.accept((HttpConnectionFactory) ReflectionTestUtils.getField(pushGateway, "connectionFactory"));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private PushGateway getPushGateway(AssertableApplicationContext context) {
|
||||||
assertThat(context).hasSingleBean(PrometheusPushGatewayManager.class);
|
assertThat(context).hasSingleBean(PrometheusPushGatewayManager.class);
|
||||||
PrometheusPushGatewayManager gatewayManager = context.getBean(PrometheusPushGatewayManager.class);
|
PrometheusPushGatewayManager gatewayManager = context.getBean(PrometheusPushGatewayManager.class);
|
||||||
Object pushGateway = ReflectionTestUtils.getField(gatewayManager, "pushGateway");
|
return (PushGateway) ReflectionTestUtils.getField(gatewayManager, "pushGateway");
|
||||||
assertThat(pushGateway).hasFieldOrPropertyWithValue("gatewayBaseURL", url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue