diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml
index ed81b2de0..1a9e97889 100644
--- a/spring-cloud-tencent-dependencies/pom.xml
+++ b/spring-cloud-tencent-dependencies/pom.xml
@@ -79,6 +79,7 @@
3.16.1
1.69
31.0.1-jre
+ 0.12.0
3.2.0
@@ -252,6 +253,12 @@
byte-buddy
${byte-buddy.version}
+
+
+ io.prometheus
+ simpleclient_pushgateway
+ ${pushgateway.version}
+
diff --git a/spring-cloud-tencent-rpc-enhancement/pom.xml b/spring-cloud-tencent-rpc-enhancement/pom.xml
index e311cbff0..e15674c47 100644
--- a/spring-cloud-tencent-rpc-enhancement/pom.xml
+++ b/spring-cloud-tencent-rpc-enhancement/pom.xml
@@ -69,6 +69,11 @@
mockito-inline
test
+
+
+ io.prometheus
+ simpleclient_pushgateway
+
\ No newline at end of file
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatProperties.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatProperties.java
index b8b918202..8e91f512a 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatProperties.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatProperties.java
@@ -17,6 +17,10 @@
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;
/**
@@ -47,6 +51,10 @@ public class PolarisStatProperties {
*/
private String path = "/metrics";
+ /**
+ * PushGatewayProperties.
+ */
+ private PushGatewayProperties pushgateway;
public boolean isEnabled() {
return enabled;
@@ -79,4 +87,108 @@ 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 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 getGroupingKeys() {
+ return groupingKeys;
+ }
+
+ public void setGroupingKeys(Map 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
+ }
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatPropertiesAutoConfiguration.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatPropertiesAutoConfiguration.java
index d21c21fba..652429fad 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatPropertiesAutoConfiguration.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/PolarisStatPropertiesAutoConfiguration.java
@@ -17,9 +17,15 @@
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.stat.config.plugin.PrometheusPushGatewayContainer;
+import org.apache.commons.lang.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -40,4 +46,36 @@ public class PolarisStatPropertiesAutoConfiguration {
public StatConfigModifier statReporterConfigModifier(PolarisStatProperties polarisStatProperties, Environment environment) {
return new StatConfigModifier(polarisStatProperties, environment);
}
+
+ @Configuration(proxyBeanMethods = false)
+ @ConditionalOnProperty(name = "spring.cloud.polaris.stat.pushgateway.enabled", havingValue = "true")
+ 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 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;
+ }
+ }
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/plugin/PrometheusPushGatewayContainer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/plugin/PrometheusPushGatewayContainer.java
new file mode 100644
index 000000000..4a689a90f
--- /dev/null
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/stat/config/plugin/PrometheusPushGatewayContainer.java
@@ -0,0 +1,129 @@
+/*
+ * 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 groupingKey;
+
+ private final ScheduledExecutorService executorService;
+ private final ScheduledFuture> scheduledFuture;
+
+ public PrometheusPushGatewayContainer(String address, Duration pushRate, String job,
+ PolarisStatProperties.ShutDownStrategy shutDownStrategy, Map 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);
+ }
+ }
+}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-tencent-rpc-enhancement/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index c76a18566..dd36d920b 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -46,6 +46,45 @@
"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",
+ "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"
}
]
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/stat/plugin/PrometheusPushGatewayContainerTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/stat/plugin/PrometheusPushGatewayContainerTest.java
new file mode 100644
index 000000000..cce877df5
--- /dev/null
+++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/stat/plugin/PrometheusPushGatewayContainerTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.plugin.PrometheusPushGatewayContainer;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+
+/**
+ * Test for {@link PrometheusPushGatewayContainer}.
+ *
+ * @author lingxiao.wlx
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = RANDOM_PORT,
+ classes = PrometheusPushGatewayContainerTest.TestApplication.class,
+ properties = {"spring.cloud.polaris.stat.pushgateway.enabled=true",
+ "spring.cloud.polaris.stat.pushgateway.shut-down-strategy=DELETE",
+ "spring.cloud.polaris.stat.pushgateway.push-rate=1m",
+ "spring.cloud.polaris.stat.pushgateway.job=test",
+ "spring.cloud.polaris.stat.pushgateway.grouping-keys.instance=test"})
+public class PrometheusPushGatewayContainerTest {
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ @Test
+ public void prometheusPushGatewayContainerTest() {
+ PolarisStatProperties polarisStatProperties = applicationContext.getBean(PolarisStatProperties.class);
+ PolarisStatProperties.PushGatewayProperties pushgateway = polarisStatProperties.getPushgateway();
+ Assertions.assertFalse(Objects.isNull(pushgateway));
+ Assertions.assertEquals(pushgateway.getJob(), "test");
+ Assertions.assertEquals(pushgateway.getPushRate().toMillis(), 60000);
+ Assertions.assertEquals(pushgateway.getShutDownStrategy(), PolarisStatProperties.ShutDownStrategy.DELETE);
+ applicationContext.getBean(PrometheusPushGatewayContainer.class);
+ }
+
+ @SpringBootApplication
+ protected static class TestApplication {
+ }
+}