feature:support pushGateway push metrics

pull/504/head
wulingxiao 3 years ago
parent 462f528e77
commit 9fb368347f

@ -17,10 +17,6 @@
package com.tencent.cloud.rpc.enhancement.stat.config;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@ -51,11 +47,6 @@ public class PolarisStatProperties {
*/
private String path = "/metrics";
/**
* PushGatewayProperties.
*/
private PushGatewayProperties pushgateway;
public boolean isEnabled() {
return enabled;
}
@ -87,108 +78,4 @@ public class PolarisStatProperties {
public void setPath(String path) {
this.path = path;
}
public PushGatewayProperties getPushgateway() {
return pushgateway;
}
public void setPushgateway(PushGatewayProperties pushgateway) {
this.pushgateway = pushgateway;
}
public static class PushGatewayProperties {
/**
* Enable publishing via a Prometheus pushGateway.
*/
private Boolean enabled = false;
/**
* Required host:port or ip:port of the pushGateway.
*/
private String address = "localhost:9091";
/**
* Required identifier for this application instance.
*/
private String job;
/**
* Frequency with which to push metrics to pushGateway,default 1 minutes.
*/
private Duration pushRate = Duration.ofMinutes(1);
/**
* PushGateway shutDownStrategy when application is is shut-down.
*/
private ShutDownStrategy shutDownStrategy;
/**
* Used to group metrics in pushGateway. eg:instance:instanceName
*/
private Map<String, String> groupingKeys = new HashMap<>();
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Duration getPushRate() {
return pushRate;
}
public void setPushRate(Duration pushRate) {
this.pushRate = pushRate;
}
public Map<String, String> getGroupingKeys() {
return groupingKeys;
}
public void setGroupingKeys(Map<String, String> groupingKeys) {
this.groupingKeys = groupingKeys;
}
public ShutDownStrategy getShutDownStrategy() {
return shutDownStrategy;
}
public void setShutDownStrategy(ShutDownStrategy shutDownStrategy) {
this.shutDownStrategy = shutDownStrategy;
}
}
/**
* PushGateway shutDownStrategy when application is is shut-down.
*/
public enum ShutDownStrategy {
/**
* Delete metrics from pushGateway when application is shut-down.
*/
DELETE,
/**
* Push metrics right before shut-down. Mostly useful for batch jobs.
*/
PUSH
}
}

@ -17,18 +17,12 @@
package com.tencent.cloud.rpc.enhancement.stat.config;
import java.time.Duration;
import java.util.Map;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.rpc.enhancement.condition.ConditionalOnPushGatewayEnabled;
import com.tencent.cloud.rpc.enhancement.stat.config.plugin.PrometheusPushGatewayContainer;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
/**
@ -38,7 +32,7 @@ import org.springframework.core.env.Environment;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled
@EnableConfigurationProperties(PolarisStatProperties.class)
@Import(PolarisStatProperties.class)
public class PolarisStatPropertiesAutoConfiguration {
@Bean
@ -46,36 +40,4 @@ public class PolarisStatPropertiesAutoConfiguration {
public StatConfigModifier statReporterConfigModifier(PolarisStatProperties polarisStatProperties, Environment environment) {
return new StatConfigModifier(polarisStatProperties, environment);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnPushGatewayEnabled
public static class PolarisStatPrometheusPushGatewayAutoConfiguration {
private static final String DEFAULT_JOB_NAME = "spring-cloud-tencent-application";
@Bean
@ConditionalOnMissingBean
public PrometheusPushGatewayContainer prometheusPushGatewayContainer(PolarisStatProperties polarisStatProperties,
Environment environment) {
PolarisStatProperties.PushGatewayProperties pushGatewayProperties = polarisStatProperties.getPushgateway();
String job = job(pushGatewayProperties, environment);
Duration pushRate = pushGatewayProperties.getPushRate();
String address = pushGatewayProperties.getAddress();
PolarisStatProperties.ShutDownStrategy shutDownStrategy = pushGatewayProperties.getShutDownStrategy();
Map<String, String> groupingKeys = pushGatewayProperties.getGroupingKeys();
return new PrometheusPushGatewayContainer(address, pushRate, job, shutDownStrategy, groupingKeys);
}
private String job(PolarisStatProperties.PushGatewayProperties pushGatewayProperties, Environment environment) {
String job = pushGatewayProperties.getJob();
if (StringUtils.isBlank(job)) {
job = environment.getProperty("spring.application.name");
}
if (StringUtils.isBlank(job)) {
job = DEFAULT_JOB_NAME;
}
return job;
}
}
}

@ -1,129 +0,0 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 com.tencent.cloud.rpc.enhancement.stat.config.plugin;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.polaris.client.util.NamedThreadFactory;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.PushGateway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* PrometheusPushGatewayContainer will push the metrics aggregated by
* {@link com.tencent.polaris.plugins.stat.prometheus.handler.PrometheusHandler} to Prometheus pushGateway.
*
* @author lingxiao.wlx
*/
public class PrometheusPushGatewayContainer {
private final Logger logger = LoggerFactory.getLogger(PrometheusPushGatewayContainer.class);
/**
* {@link com.tencent.polaris.plugins.stat.prometheus.handler.PrometheusHandler} register the Collector with
* CollectorRegistry.defaultRegistry.
*/
private final CollectorRegistry collectorRegistry = CollectorRegistry.defaultRegistry;
private final String address;
private final String job;
private final PolarisStatProperties.ShutDownStrategy shutDownStrategy;
private final PushGateway pushGateway;
private final Map<String, String> groupingKey;
private final ScheduledExecutorService executorService;
private final ScheduledFuture<?> scheduledFuture;
public PrometheusPushGatewayContainer(String address, Duration pushRate, String job,
PolarisStatProperties.ShutDownStrategy shutDownStrategy, Map<String, String> groupingKey) {
this.address = address;
this.job = job;
this.shutDownStrategy = shutDownStrategy;
this.pushGateway = new PushGateway(address);
this.groupingKey = groupingKey;
this.executorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("PrometheusPushGateway") {
@Override
public Thread newThread(Runnable r) {
Thread thread = super.newThread(r);
thread.setDaemon(true);
return thread;
}
});
this.scheduledFuture = executorService.scheduleAtFixedRate(() -> {
this.push();
if (logger.isDebugEnabled()) {
logger.debug("push metrics to Prometheus pushGateway success!");
}
}, 0, pushRate.toMillis(), TimeUnit.MILLISECONDS);
}
/**
* Call by Spring to destroy PrometheusPushGatewayContainer instance.
*/
public void shutdown() {
shutdown(this.shutDownStrategy);
}
private void shutdown(PolarisStatProperties.ShutDownStrategy shutDownStrategy) {
executorService.shutdown();
scheduledFuture.cancel(false);
if (Objects.isNull(shutDownStrategy)) {
return;
}
switch (shutDownStrategy) {
case PUSH:
push();
break;
case DELETE:
delete();
break;
}
}
private void push() {
try {
pushGateway.pushAdd(collectorRegistry, this.job, this.groupingKey);
}
catch (UnknownHostException e) {
logger.error("Unable to locate host {}. No longer attempting metrics publication to this host", this.address);
// if cache UnknownHostException,shutdown task
this.shutdown(null);
}
catch (Throwable t) {
logger.error("Unable to push metrics to Prometheus pushGateway", t);
}
}
private void delete() {
try {
pushGateway.delete(this.job, this.groupingKey);
}
catch (Throwable t) {
logger.error("Unable to delete metrics from Prometheus pushGateway", t);
}
}
}

@ -46,45 +46,6 @@
"type": "java.lang.String",
"defaultValue": "/metrics",
"description": "Path for prometheus to pull."
},
{
"name": "spring.cloud.polaris.stat.pushgateway.address",
"type": "java.lang.String",
"description": "Required host:port or ip:port of the pushGateway.",
"sourceType": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$PushGatewayProperties",
"defaultValue": "localhost:9091"
},
{
"name": "spring.cloud.polaris.stat.pushgateway.enabled",
"type": "java.lang.Boolean",
"description": "Enable publishing via a Prometheus pushGateway.",
"sourceType": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$PushGatewayProperties",
"defaultValue": false
},
{
"name": "spring.cloud.polaris.stat.pushgateway.grouping-keys",
"type": "java.util.Map<java.lang.String,java.lang.String>",
"description": "Used to group metrics in pushGateway. eg:instance:instanceName",
"sourceType": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$PushGatewayProperties"
},
{
"name": "spring.cloud.polaris.stat.pushgateway.job",
"type": "java.lang.String",
"description": "Required identifier for this application instance.",
"sourceType": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$PushGatewayProperties"
},
{
"name": "spring.cloud.polaris.stat.pushgateway.push-rate",
"type": "java.time.Duration",
"description": "Frequency with which to push metrics to pushGateway,default 1 minutes.",
"sourceType": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$PushGatewayProperties",
"defaultValue": "1m"
},
{
"name": "spring.cloud.polaris.stat.pushgateway.shut-down-strategy",
"type": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$ShutDownStrategy",
"description": "PushGateway shutDownStrategy when application is is shut-down.",
"sourceType": "com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties$PushGatewayProperties"
}
]
}

@ -1,102 +0,0 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 com.tencent.cloud.rpc.enhancement.stat.plugin;
import java.util.Objects;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatPropertiesAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.stat.config.plugin.PrometheusPushGatewayContainer;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link PrometheusPushGatewayContainer}.
*
* @author lingxiao.wlx
*/
public class PrometheusPushGatewayContainerTest {
@Test
public void testWithPushGatewayAndPushGatewayEnabled() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.enabled=true")
.withPropertyValues("spring.cloud.polaris.stat.enabled=true")
.withConfiguration(AutoConfigurations.of(PolarisStatPropertiesAutoConfiguration.class));
contextRunner.run(context -> {
assertThat(context).hasSingleBean(PrometheusPushGatewayContainer.class);
});
}
@Test
public void testWithoutPushGatewayEnabled() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.enabled=false")
.withPropertyValues("spring.cloud.polaris.stat.enabled=true")
.withConfiguration(AutoConfigurations.of(PolarisStatPropertiesAutoConfiguration.class));
contextRunner.run(context -> {
assertThat(context).doesNotHaveBean(PrometheusPushGatewayContainer.class);
});
}
@Test
public void testWithoutStatEnabled() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.enabled=true")
.withPropertyValues("spring.cloud.polaris.stat.enabled=false")
.withConfiguration(AutoConfigurations.of(PolarisStatPropertiesAutoConfiguration.class));
contextRunner.run(context -> {
assertThat(context).doesNotHaveBean(PrometheusPushGatewayContainer.class);
});
}
@Test
public void testWithoutPushGatewayAndStatEnabled() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.enabled=false")
.withPropertyValues("spring.cloud.polaris.stat.enabled=false")
.withConfiguration(AutoConfigurations.of(PolarisStatPropertiesAutoConfiguration.class));
contextRunner.run(context -> {
assertThat(context).doesNotHaveBean(PrometheusPushGatewayContainer.class);
});
}
@Test
public void testPushGatewayProperties() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.enabled=true")
.withPropertyValues("spring.cloud.polaris.stat.enabled=true")
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.job=test")
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.grouping-keys.instance=test")
.withPropertyValues("spring.cloud.polaris.stat.pushgateway.push-rate=1m")
.withConfiguration(AutoConfigurations.of(PolarisStatPropertiesAutoConfiguration.class));
contextRunner.run(context -> {
assertThat(context).hasSingleBean(PrometheusPushGatewayContainer.class);
PolarisStatProperties properties = context.getBean(PolarisStatProperties.class);
PolarisStatProperties.PushGatewayProperties pushgateway = properties.getPushgateway();
Assertions.assertFalse(Objects.isNull(pushgateway));
Assertions.assertEquals(pushgateway.getJob(), "test");
Assertions.assertEquals(pushgateway.getPushRate().toMillis(), 60000);
});
}
}
Loading…
Cancel
Save