diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml b/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml
index 58a68a422..230e50a82 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/pom.xml
@@ -96,6 +96,18 @@
+
+ org.springframework.boot
+ spring-boot-actuator
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-actuator-autoconfigure
+ true
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java
new file mode 100644
index 000000000..b2ff0eeff
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java
@@ -0,0 +1,86 @@
+/*
+ * 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.polaris.circuitbreaker.endpoint;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.util.JsonFormat;
+import com.tencent.cloud.common.metadata.MetadataContext;
+import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+
+/**
+ * Endpoint of polaris circuit breaker, include circuit breaker rules.
+ *
+ * @author wenxuan70
+ */
+@Endpoint(id = "polaris-circuit-breaker")
+public class PolarisCircuitBreakerEndpoint {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PolarisCircuitBreakerEndpoint.class);
+
+ private final ServiceRuleManager serviceRuleManager;
+
+ public PolarisCircuitBreakerEndpoint(ServiceRuleManager serviceRuleManager) {
+ this.serviceRuleManager = serviceRuleManager;
+ }
+
+ @ReadOperation
+ public Map circuitBreaker() {
+ CircuitBreakerProto.CircuitBreaker circuitBreaker = serviceRuleManager.getServiceCircuitBreakerRule(
+ MetadataContext.LOCAL_NAMESPACE,
+ MetadataContext.LOCAL_SERVICE
+ );
+
+ Map polarisCircuitBreakerInfo = new HashMap<>();
+
+ polarisCircuitBreakerInfo.put("namespace", MetadataContext.LOCAL_NAMESPACE);
+ polarisCircuitBreakerInfo.put("service", MetadataContext.LOCAL_SERVICE);
+ polarisCircuitBreakerInfo.put("circuitBreakerRules", parseCircuitBreakerRule(circuitBreaker));
+
+ return polarisCircuitBreakerInfo;
+ }
+
+ private List parseCircuitBreakerRule(CircuitBreakerProto.CircuitBreaker circuitBreaker) {
+ List circuitBreakerRuleList = new ArrayList<>();
+
+ for (CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule : circuitBreaker.getRulesList()) {
+ String ruleJson;
+ try {
+ ruleJson = JsonFormat.printer().print(circuitBreakerRule);
+ }
+ catch (InvalidProtocolBufferException e) {
+ LOG.error("rule to Json failed. check rule {}.", circuitBreakerRule, e);
+ throw new RuntimeException("Json failed.", e);
+ }
+ circuitBreakerRuleList.add(JacksonUtils.deserialize2Map(ruleJson));
+ }
+
+ return circuitBreakerRuleList;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointAutoConfiguration.java
new file mode 100644
index 000000000..6c9073925
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointAutoConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * 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.polaris.circuitbreaker.endpoint;
+
+import com.tencent.cloud.polaris.circuitbreaker.config.ConditionalOnPolarisCircuitBreakerEnabled;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+
+import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * The AutoConfiguration for Polaris CircuitBreaker's Endpoint.
+ *
+ * @author wenxuan70
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnClass(Endpoint.class)
+@ConditionalOnPolarisCircuitBreakerEnabled
+public class PolarisCircuitBreakerEndpointAutoConfiguration {
+
+ @Bean
+ @ConditionalOnBean(ServiceRuleManager.class)
+ @ConditionalOnMissingBean
+ @ConditionalOnAvailableEndpoint
+ public PolarisCircuitBreakerEndpoint polarisCircuitBreakerEndpoint(ServiceRuleManager serviceRuleManager) {
+ return new PolarisCircuitBreakerEndpoint(serviceRuleManager);
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories
index a873ed563..07972a65c 100644
--- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/resources/META-INF/spring.factories
@@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration,\
com.tencent.cloud.polaris.circuitbreaker.config.ReactivePolarisCircuitBreakerAutoConfiguration,\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerFeignClientAutoConfiguration,\
- com.tencent.cloud.polaris.circuitbreaker.config.GatewayPolarisCircuitBreakerAutoConfiguration
+ com.tencent.cloud.polaris.circuitbreaker.config.GatewayPolarisCircuitBreakerAutoConfiguration,\
+ com.tencent.cloud.polaris.circuitbreaker.endpoint.PolarisCircuitBreakerEndpointAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerBootstrapConfiguration
diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java
new file mode 100644
index 000000000..23913957e
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.polaris.circuitbreaker.endpoint;
+
+import java.util.Map;
+
+import com.google.protobuf.StringValue;
+import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
+import com.tencent.cloud.polaris.context.ServiceRuleManager;
+import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
+import com.tencent.polaris.specification.api.v1.model.ModelProto;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
+import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test for {@link PolarisCircuitBreakerEndpoint}.
+ *
+ * @author wenxuan70
+ */
+@ExtendWith(MockitoExtension.class)
+public class PolarisCircuitBreakerEndpointTest {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withBean(ApplicationContextAwareUtils.class)
+ .withPropertyValues("spring.cloud.polaris.namespace=" + NAMESPACE_TEST)
+ .withPropertyValues("spring.cloud.polaris.service=" + SERVICE_PROVIDER);
+
+ private ServiceRuleManager serviceRuleManager;
+
+ @BeforeEach
+ void setUp() {
+ serviceRuleManager = mock(ServiceRuleManager.class);
+ when(serviceRuleManager.getServiceCircuitBreakerRule(anyString(), anyString())).thenAnswer(invocation -> {
+ CircuitBreakerProto.CircuitBreakerRule.Builder ruleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder();
+ ruleBuilder.setName("test_for_circuit_breaker");
+ ruleBuilder.setEnable(true);
+ ruleBuilder.setLevel(CircuitBreakerProto.Level.METHOD);
+ CircuitBreakerProto.RuleMatcher.Builder rmBuilder = CircuitBreakerProto.RuleMatcher.newBuilder();
+ rmBuilder.setDestination(CircuitBreakerProto.RuleMatcher.DestinationService.newBuilder().setNamespace("default").setService("svc2").setMethod(
+ ModelProto.MatchString.newBuilder().setValue(StringValue.newBuilder().setValue("*").build()).build()).build());
+ rmBuilder.setSource(CircuitBreakerProto.RuleMatcher.SourceService.newBuilder().setNamespace("*").setService("*").build());
+ ruleBuilder.setRuleMatcher(rmBuilder.build());
+ return CircuitBreakerProto.CircuitBreaker.newBuilder().addRules(ruleBuilder.build()).build();
+ });
+ }
+
+ @Test
+ public void testPolarisCircuitBreaker() {
+ contextRunner.run(context -> {
+ PolarisCircuitBreakerEndpoint endpoint = new PolarisCircuitBreakerEndpoint(serviceRuleManager);
+ Map circuitBreakerInfo = endpoint.circuitBreaker();
+ assertThat(circuitBreakerInfo).isNotNull();
+ assertThat(circuitBreakerInfo.get("namespace")).isNotNull();
+ assertThat(circuitBreakerInfo.get("service")).isNotNull();
+ assertThat(circuitBreakerInfo.get("circuitBreakerRules")).asList().isNotEmpty();
+ });
+ }
+}
diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java
index 128899491..3dff09e8e 100644
--- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java
+++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java
@@ -27,13 +27,14 @@ import com.tencent.polaris.api.pojo.ServiceRule;
import com.tencent.polaris.api.rpc.GetServiceRuleRequest;
import com.tencent.polaris.api.rpc.ServiceRuleResponse;
import com.tencent.polaris.client.api.SDKContext;
+import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto;
import com.tencent.polaris.specification.api.v1.traffic.manage.RateLimitProto;
import com.tencent.polaris.specification.api.v1.traffic.manage.RoutingProto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * the manager of service governance rules. for example: rate limit rule, router rules.
+ * the manager of service governance rules. for example: rate limit rule, router rules, circuit breaker rules.
*
* @author lepdou 2022-05-13
*/
@@ -88,6 +89,20 @@ public class ServiceRuleManager {
return rules;
}
+ public CircuitBreakerProto.CircuitBreaker getServiceCircuitBreakerRule(String namespace, String service) {
+ LOG.debug("Get service circuit breaker rules with namespace:{} and service:{}.", namespace, service);
+
+ ServiceRule serviceRule = getServiceRule("", "", ServiceEventKey.EventType.CIRCUIT_BREAKING);
+ if (serviceRule != null) {
+ Object rule = serviceRule.getRule();
+ if (rule instanceof CircuitBreakerProto.CircuitBreaker) {
+ return (CircuitBreakerProto.CircuitBreaker) rule;
+ }
+ }
+
+ return null;
+ }
+
private ServiceRule getServiceRule(String namespace, String service, ServiceEventKey.EventType eventType) {
GetServiceRuleRequest getServiceRuleRequest = new GetServiceRuleRequest();
getServiceRuleRequest.setRuleType(eventType);