Commit 20ecf73c authored by Phillip Webb's avatar Phillip Webb

Polish "Add Prometheus push gateway support"

Rework Prometheus push gateway support so that the central class can
be used outside of auto-configuration. The shutdown flags have also
been replaced with a single "shutdown-operation" property since it's
unlikely that both "push" and "delete" will be required.

It's also possible now to supply a `TaskScheduler` to the manager.

See gh-14353
parent 4e71981f
......@@ -16,25 +16,21 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus;
import java.net.UnknownHostException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.PreDestroy;
import java.time.Duration;
import java.util.Map;
import io.micrometer.core.instrument.Clock;
import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.PushGateway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
......@@ -53,6 +49,7 @@ import org.springframework.core.env.Environment;
*
* @since 2.0.0
* @author Jon Schneider
* @author David J. M. Karlsen
*/
@Configuration
@AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class,
......@@ -100,108 +97,42 @@ public class PrometheusMetricsExportAutoConfiguration {
/**
* Configuration for <a href="https://github.com/prometheus/pushgateway">Prometheus
* Pushgateway</a>.
*
* @author David J. M. Karlsen
*/
@Configuration
@ConditionalOnClass(PushGateway.class)
@ConditionalOnProperty(prefix = "management.metrics.export.prometheus.pushgateway", name = "enabled")
public static class PrometheusPushGatewayConfiguration {
/**
* The fallback job name. We use 'spring' since there's a history of Prometheus
* spring integration defaulting to that name from when Prometheus integration
* didn't exist in Spring itself.
*/
private static final String FALLBACK_JOB = "spring";
@Bean
public PushGatewayHandler pushGatewayHandler(CollectorRegistry collectorRegistry,
@ConditionalOnMissingBean
public PrometheusPushGatewayManager prometheusPushGatewayManager(
CollectorRegistry collectorRegistry,
PrometheusProperties prometheusProperties, Environment environment) {
return new PushGatewayHandler(collectorRegistry, prometheusProperties,
environment);
PrometheusProperties.Pushgateway properties = prometheusProperties
.getPushgateway();
PushGateway pushGateway = new PushGateway(properties.getBaseUrl());
Duration pushRate = properties.getPushRate();
String job = getJob(properties, environment);
Map<String, String> groupingKey = properties.getGroupingKey();
ShutdownOperation shutdownOperation = properties.getShutdownOperation();
return new PrometheusPushGatewayManager(pushGateway, collectorRegistry,
pushRate, job, groupingKey, shutdownOperation);
}
static class PushGatewayHandler {
private final Logger logger = LoggerFactory
.getLogger(PrometheusPushGatewayConfiguration.class);
private final CollectorRegistry collectorRegistry;
private final PrometheusProperties.PushgatewayProperties pushgatewayProperties;
private final PushGateway pushGateway;
private final Environment environment;
private final ScheduledExecutorService executorService;
PushGatewayHandler(CollectorRegistry collectorRegistry,
PrometheusProperties prometheusProperties, Environment environment) {
this.collectorRegistry = collectorRegistry;
this.pushgatewayProperties = prometheusProperties.getPushgateway();
this.pushGateway = new PushGateway(
this.pushgatewayProperties.getBaseUrl());
this.environment = environment;
this.executorService = Executors.newSingleThreadScheduledExecutor((r) -> {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("micrometer-pushgateway");
return thread;
});
this.executorService.scheduleAtFixedRate(this::push, 0,
this.pushgatewayProperties.getPushRate().toMillis(),
TimeUnit.MILLISECONDS);
}
void push() {
try {
this.pushGateway.pushAdd(this.collectorRegistry, getJobName(),
this.pushgatewayProperties.getGroupingKeys());
}
catch (UnknownHostException ex) {
this.logger.error("Unable to locate host '"
+ this.pushgatewayProperties.getBaseUrl()
+ "'. No longer attempting metrics publication to this host");
this.executorService.shutdown();
}
catch (Throwable throwable) {
this.logger.error("Unable to push metrics to Prometheus Pushgateway",
throwable);
}
}
@PreDestroy
void shutdown() {
this.executorService.shutdown();
if (this.pushgatewayProperties.isPushOnShutdown()) {
push();
}
if (this.pushgatewayProperties.isDeleteOnShutdown()) {
delete();
}
}
private void delete() {
try {
this.pushGateway.delete(getJobName(),
this.pushgatewayProperties.getGroupingKeys());
}
catch (Throwable throwable) {
this.logger.error(
"Unable to delete metrics from Prometheus Pushgateway",
throwable);
}
}
private String getJobName() {
String job = this.pushgatewayProperties.getJob();
if (job == null) {
job = this.environment.getProperty("spring.application.name");
}
if (job == null) {
// There's a history of Prometheus spring integration defaulting the
// getJobName name to "spring" from when
// Prometheus integration didn't exist in Spring itself.
job = "spring";
}
return job;
}
private String getJob(PrometheusProperties.Pushgateway properties,
Environment environment) {
String job = properties.getJob();
job = (job != null) ? job
: environment.getProperty("spring.application.name");
job = (job != null) ? job : FALLBACK_JOB;
return job;
}
}
......
......@@ -20,6 +20,7 @@ import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
......@@ -42,7 +43,7 @@ public class PrometheusProperties {
* Configuration options for using Prometheus Pushgateway, allowing metrics to be
* pushed when they cannot be scraped.
*/
private PushgatewayProperties pushgateway = new PushgatewayProperties();
private Pushgateway pushgateway = new Pushgateway();
/**
* Step size (i.e. reporting frequency) to use.
......@@ -65,18 +66,18 @@ public class PrometheusProperties {
this.step = step;
}
public PushgatewayProperties getPushgateway() {
public Pushgateway getPushgateway() {
return this.pushgateway;
}
public void setPushgateway(PushgatewayProperties pushgateway) {
public void setPushgateway(Pushgateway pushgateway) {
this.pushgateway = pushgateway;
}
/**
* Configuration options for push-based interaction with Prometheus.
*/
public static class PushgatewayProperties {
public static class Pushgateway {
/**
* Enable publishing via a Prometheus Pushgateway.
......@@ -84,34 +85,29 @@ public class PrometheusProperties {
private Boolean enabled = false;
/**
* Required host:port or ip:port of the Pushgateway.
* Base URL for the Pushgateway.
*/
private String baseUrl = "localhost:9091";
/**
* Required identifier for this application instance.
*/
private String job;
/**
* Frequency with which to push metrics to Pushgateway.
* Frequency with which to push metrics.
*/
private Duration pushRate = Duration.ofMinutes(1);
/**
* Push metrics right before shut-down. Mostly useful for batch jobs.
* Job identifier for this application instance.
*/
private boolean pushOnShutdown = true;
private String job;
/**
* Delete metrics from Pushgateway when application is shut-down.
* Grouping key for the pushed metrics.
*/
private boolean deleteOnShutdown = true;
private Map<String, String> groupingKey = new HashMap<>();
/**
* Used to group metrics in pushgateway. A common example is setting
* Operation that should be performed on shutdown.
*/
private Map<String, String> groupingKeys = new HashMap<>();
private ShutdownOperation shutdownOperation = ShutdownOperation.NONE;
public Boolean getEnabled() {
return this.enabled;
......@@ -129,14 +125,6 @@ public class PrometheusProperties {
this.baseUrl = baseUrl;
}
public String getJob() {
return this.job;
}
public void setJob(String job) {
this.job = job;
}
public Duration getPushRate() {
return this.pushRate;
}
......@@ -145,28 +133,28 @@ public class PrometheusProperties {
this.pushRate = pushRate;
}
public boolean isPushOnShutdown() {
return this.pushOnShutdown;
public String getJob() {
return this.job;
}
public void setPushOnShutdown(boolean pushOnShutdown) {
this.pushOnShutdown = pushOnShutdown;
public void setJob(String job) {
this.job = job;
}
public boolean isDeleteOnShutdown() {
return this.deleteOnShutdown;
public Map<String, String> getGroupingKey() {
return this.groupingKey;
}
public void setDeleteOnShutdown(boolean deleteOnShutdown) {
this.deleteOnShutdown = deleteOnShutdown;
public void setGroupingKey(Map<String, String> groupingKey) {
this.groupingKey = groupingKey;
}
public Map<String, String> getGroupingKeys() {
return this.groupingKeys;
public ShutdownOperation getShutdownOperation() {
return this.shutdownOperation;
}
public void setGroupingKeys(Map<String, String> groupingKeys) {
this.groupingKeys = groupingKeys;
public void setShutdownOperation(ShutdownOperation shutdownOperation) {
this.shutdownOperation = shutdownOperation;
}
}
......
......@@ -22,8 +22,8 @@ import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.prometheus.client.CollectorRegistry;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusMetricsExportAutoConfiguration.PrometheusPushGatewayConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
......@@ -137,8 +137,8 @@ public class PrometheusMetricsExportAutoConfigurationTests {
.withPropertyValues(
"management.metrics.export.prometheus.pushgateway.enabled=true")
.withUserConfiguration(BaseConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(
PrometheusPushGatewayConfiguration.PushGatewayHandler.class));
.run((context) -> assertThat(context)
.hasSingleBean(PrometheusPushGatewayManager.class));
}
@Configuration
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
......@@ -61,6 +62,11 @@
<artifactId>micrometer-registry-prometheus</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_pushgateway</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava-reactive-streams</artifactId>
......
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.metrics.export.prometheus;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.PushGateway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Class that can be used to managed the pushing of metrics to a {@link PushGateway
* Prometheus PushGateway}. Handles the scheduling of push operations, error handling and
* shutdown operations.
*
* @author David J. M. Karlsen
* @author Phillip Webb
* @since 2.1.0
*/
public class PrometheusPushGatewayManager {
private static final Logger logger = LoggerFactory
.getLogger(PrometheusPushGatewayManager.class);
private final PushGateway pushGateway;
private final CollectorRegistry registry;
private final String job;
private final Map<String, String> groupingKey;
private final ShutdownOperation shutdownOperation;
private final TaskScheduler scheduler;
private ScheduledFuture<?> scheduled;
/**
* Create a new {@link PrometheusPushGatewayManager} instance using a single threaded
* {@link TaskScheduler}.
* @param pushGateway the source push gateway
* @param registry the collector registry to push
* @param pushRate the rate at which push operations occur
* @param job the job ID for the operation
* @param groupingKeys an optional set of grouping keys for the operation
* @param shutdownOperation the shutdown operation that should be performed when
* context is closed.
*/
public PrometheusPushGatewayManager(PushGateway pushGateway,
CollectorRegistry registry, Duration pushRate, String job,
Map<String, String> groupingKeys, ShutdownOperation shutdownOperation) {
this(pushGateway, registry, new PushGatewayTaskScheduler(), pushRate, job,
groupingKeys, shutdownOperation);
}
/**
* Create a new {@link PrometheusPushGatewayManager} instance.
* @param pushGateway the source push gateway
* @param registry the collector registry to push
* @param scheduler the scheduler used for operations
* @param pushRate the rate at which push operations occur
* @param job the job ID for the operation
* @param groupingKey an optional set of grouping keys for the operation
* @param shutdownOperation the shutdown operation that should be performed when
* context is closed.
*/
public PrometheusPushGatewayManager(PushGateway pushGateway,
CollectorRegistry registry, TaskScheduler scheduler, Duration pushRate,
String job, Map<String, String> groupingKey,
ShutdownOperation shutdownOperation) {
Assert.notNull(pushGateway, "PushGateway must not be null");
Assert.notNull(registry, "Registry must not be null");
Assert.notNull(scheduler, "Scheduler must not be null");
Assert.notNull(pushRate, "PushRate must not be null");
Assert.hasLength(job, "Job must not be empty");
this.pushGateway = pushGateway;
this.registry = registry;
this.job = job;
this.groupingKey = groupingKey;
this.shutdownOperation = (shutdownOperation != null) ? shutdownOperation
: ShutdownOperation.NONE;
this.scheduler = scheduler;
this.scheduled = this.scheduler.scheduleAtFixedRate(this::push, pushRate);
}
private void push() {
try {
this.pushGateway.pushAdd(this.registry, this.job, this.groupingKey);
}
catch (UnknownHostException ex) {
String host = ex.getMessage();
String message = "Unable to locate prometheus push gateway host";
message += StringUtils.hasLength(host) ? " '" + host + "'" : "";
message += ". No longer attempting metrics publication to this host";
logger.error(message, ex);
shutdown(ShutdownOperation.NONE);
}
catch (Throwable ex) {
logger.error("Unable to push metrics to Prometheus Pushgateway", ex);
}
}
private void delete() {
try {
this.pushGateway.delete(this.job, this.groupingKey);
}
catch (Throwable ex) {
logger.error("Unable to delete metrics from Prometheus Pushgateway", ex);
}
}
/**
* Shutdown the manager, running any {@link ShutdownOperation}.
*/
public void shutdown() {
shutdown(this.shutdownOperation);
}
private void shutdown(ShutdownOperation shutdownOperation) {
if (this.scheduler instanceof PushGatewayTaskScheduler) {
((PushGatewayTaskScheduler) this.scheduler).shutdown();
}
this.scheduled.cancel(false);
switch (shutdownOperation) {
case PUSH:
push();
break;
case DELETE:
delete();
break;
}
}
/**
* The operation that should be performed on shutdown.
*/
public enum ShutdownOperation {
/**
* Don't perform any shutdown operation.
*/
NONE,
/**
* Perform a 'push' before shutdown.
*/
PUSH,
/**
* Perform a 'delete' before shutdown.
*/
DELETE
}
/**
* {@link TaskScheduler} used when the user doesn't specify one.
*/
static class PushGatewayTaskScheduler extends ThreadPoolTaskScheduler {
PushGatewayTaskScheduler() {
setPoolSize(1);
setDaemon(true);
setThreadGroupName("prometheus-push-gateway");
}
@Override
public ScheduledExecutorService getScheduledExecutor()
throws IllegalStateException {
return Executors.newSingleThreadScheduledExecutor(this::newThread);
}
}
}
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.metrics.export.prometheus;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.PushGateway;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.PushGatewayTaskScheduler;
import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusPushGatewayManager.ShutdownOperation;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link PrometheusPushGatewayManager}.
*
* @author Phillip Webb
*/
public class PrometheusPushGatewayManagerTests {
@Mock
private PushGateway pushGateway;
@Mock
private CollectorRegistry registry;
private TaskScheduler scheduler;
private Duration pushRate = Duration.ofSeconds(1);
private Map<String, String> groupingKey = Collections.singletonMap("foo", "bar");
@Captor
private ArgumentCaptor<Runnable> task;
@Mock
private ScheduledFuture<Object> future;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.scheduler = mockScheduler(TaskScheduler.class);
}
@Test
public void createWhenPushGatewayIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new PrometheusPushGatewayManager(null, this.registry,
this.scheduler, this.pushRate, "job", this.groupingKey, null))
.withMessage("PushGateway must not be null");
}
@Test
public void createWhenCollectorRegistryIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new PrometheusPushGatewayManager(this.pushGateway, null,
this.scheduler, this.pushRate, "job", this.groupingKey, null))
.withMessage("Registry must not be null");
}
@Test
public void createWhenSchedulerIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> new PrometheusPushGatewayManager(this.pushGateway, this.registry,
null, this.pushRate, "job", this.groupingKey, null))
.withMessage("Scheduler must not be null");
}
@Test
public void createWhenPushRateIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> new PrometheusPushGatewayManager(this.pushGateway, this.registry,
this.scheduler, null, "job", this.groupingKey, null))
.withMessage("PushRate must not be null");
}
@Test
public void createWhenJobIsEmptyThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> new PrometheusPushGatewayManager(this.pushGateway, this.registry,
this.scheduler, this.pushRate, "", this.groupingKey, null))
.withMessage("Job must not be empty");
}
@Test
public void createShouldSchedulePushAsFixedRate() throws Exception {
new PrometheusPushGatewayManager(this.pushGateway, this.registry, this.scheduler,
this.pushRate, "job", this.groupingKey, null);
verify(this.scheduler).scheduleAtFixedRate(this.task.capture(),
eq(this.pushRate));
this.task.getValue().run();
verify(this.pushGateway).pushAdd(this.registry, "job", this.groupingKey);
}
@Test
public void shutdownWhenOwnsSchedulerDoesShutdownScheduler() {
PushGatewayTaskScheduler ownedScheduler = mockScheduler(
PushGatewayTaskScheduler.class);
PrometheusPushGatewayManager manager = new PrometheusPushGatewayManager(
this.pushGateway, this.registry, ownedScheduler, this.pushRate, "job",
this.groupingKey, null);
manager.shutdown();
verify(ownedScheduler).shutdown();
}
@Test
public void shutdownWhenDoesNotOwnSchedulerDoesNotShutdownScheduler() {
ThreadPoolTaskScheduler otherScheduler = mockScheduler(
ThreadPoolTaskScheduler.class);
PrometheusPushGatewayManager manager = new PrometheusPushGatewayManager(
this.pushGateway, this.registry, otherScheduler, this.pushRate, "job",
this.groupingKey, null);
manager.shutdown();
verify(otherScheduler, never()).shutdown();
}
@Test
public void shutdownWhenShutdownOperationIsPushPerformsPushOnShutdown()
throws Exception {
PrometheusPushGatewayManager manager = new PrometheusPushGatewayManager(
this.pushGateway, this.registry, this.scheduler, this.pushRate, "job",
this.groupingKey, ShutdownOperation.PUSH);
manager.shutdown();
verify(this.future).cancel(false);
verify(this.pushGateway).pushAdd(this.registry, "job", this.groupingKey);
}
@Test
public void shutdownWhenShutdownOperationIsDeletePerformsDeleteOnShutdown()
throws Exception {
PrometheusPushGatewayManager manager = new PrometheusPushGatewayManager(
this.pushGateway, this.registry, this.scheduler, this.pushRate, "job",
this.groupingKey, ShutdownOperation.DELETE);
manager.shutdown();
verify(this.future).cancel(false);
verify(this.pushGateway).delete("job", this.groupingKey);
}
@Test
public void shutdownWhenShutdownOperationIsNoneDoesNothing() {
PrometheusPushGatewayManager manager = new PrometheusPushGatewayManager(
this.pushGateway, this.registry, this.scheduler, this.pushRate, "job",
this.groupingKey, ShutdownOperation.NONE);
manager.shutdown();
verify(this.future).cancel(false);
verifyZeroInteractions(this.pushGateway);
}
@Test
public void pushWhenUnknownHostExceptionIsThrownDoesShutdown() throws Exception {
new PrometheusPushGatewayManager(this.pushGateway, this.registry, this.scheduler,
this.pushRate, "job", this.groupingKey, null);
verify(this.scheduler).scheduleAtFixedRate(this.task.capture(),
eq(this.pushRate));
willThrow(new UnknownHostException("foo")).given(this.pushGateway)
.pushAdd(this.registry, "job", this.groupingKey);
this.task.getValue().run();
verify(this.future).cancel(false);
}
@Test
public void pushDoesNotThrowException() throws Exception {
new PrometheusPushGatewayManager(this.pushGateway, this.registry, this.scheduler,
this.pushRate, "job", this.groupingKey, null);
verify(this.scheduler).scheduleAtFixedRate(this.task.capture(),
eq(this.pushRate));
willThrow(RuntimeException.class).given(this.pushGateway).pushAdd(this.registry,
"job", this.groupingKey);
this.task.getValue().run();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private <T extends TaskScheduler> T mockScheduler(Class<T> type) {
T scheduler = mock(type);
given(scheduler.scheduleAtFixedRate(isA(Runnable.class), isA(Duration.class)))
.willReturn((ScheduledFuture) this.future);
return scheduler;
}
}
......@@ -143,7 +143,6 @@
<nio-multipart-parser.version>1.1.0</nio-multipart-parser.version>
<pooled-jms-version>1.0.3</pooled-jms-version>
<postgresql.version>42.2.5</postgresql.version>
<!-- need to take care that this version harmonizes with micrometer ones -->
<prometheus-pushgateway.version>0.5.0</prometheus-pushgateway.version>
<quartz.version>2.3.0</quartz.version>
<querydsl.version>4.2.1</querydsl.version>
......
......@@ -1480,6 +1480,12 @@ content into your application. Rather, pick only the properties that you need.
management.metrics.export.prometheus.descriptions=true # Whether to enable publishing descriptions as part of the scrape payload to Prometheus. Turn this off to minimize the amount of data sent on each scrape.
management.metrics.export.prometheus.enabled=true # Whether exporting of metrics to Prometheus is enabled.
management.metrics.export.prometheus.step=1m # Step size (i.e. reporting frequency) to use.
management.metrics.export.prometheus.pushgateway.base-url=localhost:9091 # Base URL for the Pushgateway.
management.metrics.export.prometheus.pushgateway.enabled=false # Enable publishing via a Prometheus Pushgateway.
management.metrics.export.prometheus.pushgateway.grouping-key= # Grouping key for the pushed metrics.
management.metrics.export.prometheus.pushgateway.job= # Job identifier for this application instance.
management.metrics.export.prometheus.pushgateway.push-rate=1m # Frequency with which to push metrics.
management.metrics.export.prometheus.pushgateway.shutdown-operation= # Operation that should be performed on shutdown (none, push, delete).
management.metrics.export.signalfx.access-token= # SignalFX access token.
management.metrics.export.signalfx.batch-size=10000 # Number of measurements per request to use for this backend. If more measurements are found, then multiple requests will be made.
management.metrics.export.signalfx.connect-timeout=1s # Connection timeout for requests to this backend.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment