Feature: add AssemblyFlow to support tsf (#992)

pull/1000/head
Shanyou Yu (Sean Yu) 2 years ago committed by GitHub
parent 97f5ec54d0
commit d68bf433a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,3 +4,4 @@
- [feature: support reactive discovery client health indicator.](https://github.com/Tencent/spring-cloud-tencent/pull/988)
- [feature: Enhance default configuration to support `application*.yaml` and `bootstrap*.yaml`.](https://github.com/Tencent/spring-cloud-tencent/pull/988)
- [feat:Remove error log from `DecodeTransferMetadataReactiveFilter`.](https://github.com/Tencent/spring-cloud-tencent/pull/991)
- [Feature: add AssemblyFlow to support tsf.](https://github.com/Tencent/spring-cloud-tencent/pull/992)

@ -66,15 +66,15 @@ public class PolarisCircuitBreakerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean

@ -64,15 +64,15 @@ public class ReactivePolarisCircuitBreakerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI);
CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
}
@Bean

@ -19,32 +19,38 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
/**
* ExceptionCircuitBreakerReporter.
*
* @author sean yu
*/
public class ExceptionCircuitBreakerReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionCircuitBreakerReporter.class);
private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context);
this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI;
}
@ -55,19 +61,19 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION;
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ResourceStat resourceStat = createInstanceResourceStat(
ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),
@ -92,6 +98,6 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 2;
return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
}
}

@ -19,35 +19,40 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
/**
* SuccessCircuitBreakerReporter.
*
* @author sean yu
*/
public class SuccessCircuitBreakerReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context);
this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI;
}
@ -58,19 +63,19 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.POST;
return EnhancedPluginType.Client.POST;
}
@Override
public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance serviceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ResourceStat resourceStat = createInstanceResourceStat(
ResourceStat resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),
@ -94,6 +99,6 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 2;
return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
}
}

@ -95,7 +95,7 @@ public class ExceptionCircuitBreakerReporterTest {
@Test
public void testType() {
assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION);
assertThat(exceptionCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
}
@Test
@ -121,7 +121,7 @@ public class ExceptionCircuitBreakerReporterTest {
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
pluginContext.setThrowable(new RuntimeException());
exceptionCircuitBreakerReporter.run(pluginContext);

@ -40,6 +40,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
@ -74,6 +75,12 @@ public class SuccessCircuitBreakerReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -94,7 +101,7 @@ public class SuccessCircuitBreakerReporterTest {
@Test
public void testType() {
assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.POST);
assertThat(successCircuitBreakerReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST);
}
@Test
@ -120,7 +127,7 @@ public class SuccessCircuitBreakerReporterTest {
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
successCircuitBreakerReporter.run(pluginContext);
successCircuitBreakerReporter.getOrder();

@ -45,6 +45,11 @@ public class PolarisDiscoveryProperties {
@Value("${spring.cloud.polaris.discovery.service:${spring.cloud.polaris.service:${spring.application.name:}}}")
private String service;
/**
* Service instance id.
*/
private String instanceId;
/**
* The polaris authentication token.
*/
@ -96,6 +101,14 @@ public class PolarisDiscoveryProperties {
*/
private Long serviceListRefreshInterval = 60000L;
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getNamespace() {
return namespace;
}
@ -204,6 +217,7 @@ public class PolarisDiscoveryProperties {
return "PolarisDiscoveryProperties{" +
"namespace='" + namespace + '\'' +
", service='" + service + '\'' +
", instanceId='" + instanceId + '\'' +
", token='" + token + '\'' +
", weight=" + weight +
", version='" + version + '\'' +

@ -17,15 +17,25 @@
package com.tencent.cloud.polaris.loadbalancer;
import java.util.ArrayList;
import java.util.List;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
/**
* Auto-configuration of loadbalancer for Polaris.
@ -41,4 +51,23 @@ import org.springframework.context.annotation.Configuration;
@LoadBalancerClients(defaultConfiguration = PolarisLoadBalancerClientConfiguration.class)
public class PolarisLoadBalancerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(@Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
// LoadBalancerInterceptor must invoke before EnhancedRestTemplateInterceptor
if (loadBalancerInterceptor != null) {
int addIndex = list.size();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof EnhancedRestTemplateInterceptor) {
addIndex = i;
}
}
list.add(addIndex, loadBalancerInterceptor);
}
restTemplate.setInterceptors(list);
};
}
}

@ -36,7 +36,7 @@ public final class PolarisLoadBalancerRingHashKeyProvider {
}
static String getHashKey() {
return MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_HASH_KEY);
return (String) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_HASH_KEY);
}
}

@ -17,6 +17,9 @@
package com.tencent.cloud.polaris.registry;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,10 +39,17 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
private final PolarisRegistration registration;
public PolarisAutoServiceRegistration(ServiceRegistry<PolarisRegistration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) {
private final AssemblyAPI assemblyAPI;
public PolarisAutoServiceRegistration(
ServiceRegistry<PolarisRegistration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration,
AssemblyAPI assemblyAPI
) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
this.assemblyAPI = assemblyAPI;
}
@Override
@ -58,6 +68,9 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
LOGGER.debug("Registration disabled.");
return;
}
if (assemblyAPI != null) {
assemblyAPI.initService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE));
}
super.register();
}

@ -114,6 +114,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
instanceRegisterRequest.setMetadata(registration.getMetadata());
instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol());
instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion());
instanceRegisterRequest.setInstanceId(polarisDiscoveryProperties.getInstanceId());
try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI();
InstanceRegisterResponse instanceRegisterResponse;

@ -26,6 +26,7 @@ import com.tencent.cloud.polaris.discovery.PolarisDiscoveryHandler;
import com.tencent.cloud.polaris.extend.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired;
@ -78,9 +79,13 @@ public class PolarisServiceRegistryAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(
PolarisServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration,
@Autowired(required = false) AssemblyAPI assemblyAPI
) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration, assemblyAPI);
}
@Bean

@ -85,10 +85,15 @@ public class PolarisDiscoveryPropertiesTest {
polarisDiscoveryProperties.setServiceListRefreshInterval(1000L);
assertThat(polarisDiscoveryProperties.getServiceListRefreshInterval()).isEqualTo(1000L);
// InstanceId
polarisDiscoveryProperties.setInstanceId("test-ins-id");
assertThat(polarisDiscoveryProperties.getInstanceId()).isEqualTo("test-ins-id");
assertThat(polarisDiscoveryProperties.toString())
.isEqualTo("PolarisDiscoveryProperties{"
+ "namespace='Test'"
+ ", service='java_provider_test'"
+ ", instanceId='test-ins-id'"
+ ", token='19485a7674294e3c88dba293373c1534'"
+ ", weight=10, version='1.0.0'"
+ ", protocol='HTTP'"

@ -75,7 +75,7 @@ public class PolarisAutoServiceRegistrationTest {
doNothing().when(serviceRegistry).register(nullable(PolarisRegistration.class));
polarisAutoServiceRegistration =
new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration);
new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration, null);
doReturn(environment).when(applicationContext).getEnvironment();
polarisAutoServiceRegistration.setApplicationContext(applicationContext);

@ -33,9 +33,9 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerRequest;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.exception.ErrorCode;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.pojo.Instance;

@ -24,7 +24,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;

@ -22,10 +22,10 @@ import java.util.List;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor;
import com.tencent.cloud.polaris.router.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

@ -41,7 +41,7 @@ import com.tencent.cloud.polaris.router.interceptor.RuleBasedRouterRequestInterc
import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerRequest;
import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor;
import com.tencent.cloud.polaris.router.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;

@ -24,7 +24,7 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.router.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;

@ -20,7 +20,7 @@ package com.tencent.cloud.polaris.router.config;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier;
import com.tencent.cloud.polaris.router.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.polaris.router.api.core.RouterAPI;
import org.junit.jupiter.api.Test;

@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.router.transformer;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.Instance;
import org.junit.jupiter.api.BeforeAll;

@ -48,11 +48,6 @@ public class MetadataContext {
*/
public static final String FRAGMENT_DISPOSABLE = "disposable";
/**
* load balancer context.
*/
public static final String FRAGMENT_LOAD_BALANCER = "loadbalancer";
/**
* upstream disposable Context.
*/
@ -115,8 +110,12 @@ public class MetadataContext {
private final Map<String, Map<String, String>> fragmentContexts;
private final Map<String, Object> loadbalancerMetadata;
public MetadataContext() {
this.fragmentContexts = new ConcurrentHashMap<>();
this.loadbalancerMetadata = new ConcurrentHashMap<>();
}
public Map<String, String> getDisposableMetadata() {
@ -148,8 +147,8 @@ public class MetadataContext {
return this.getFragmentContext(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV);
}
public Map<String, String> getLoadbalancerMetadata() {
return this.getFragmentContext(FRAGMENT_LOAD_BALANCER);
public Map<String, Object> getLoadbalancerMetadata() {
return this.loadbalancerMetadata;
}
public void setTransitiveMetadata(Map<String, String> transitiveMetadata) {
@ -172,8 +171,8 @@ public class MetadataContext {
this.putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
}
public void setLoadbalancer(String key, String value) {
this.putContext(FRAGMENT_LOAD_BALANCER, key, value);
public void setLoadbalancer(String key, Object value) {
this.loadbalancerMetadata.put(key, value);
}
public Map<String, String> getFragmentContext(String fragment) {

@ -73,7 +73,7 @@
<revision>1.12.0-2022.0.1-SNAPSHOT</revision>
<!-- Dependencies -->
<polaris.version>1.12.3</polaris.version>
<polaris.version>1.13.0-SNAPSHOT</polaris.version>
<guava.version>31.1-jre</guava.version>
<mocktio.version>4.9.0</mocktio.version>
<byte-buddy.version>1.12.19</byte-buddy.version>
@ -164,6 +164,12 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-starter-tencent-tsf-adapter-plugin</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-featureenv-plugin</artifactId>

@ -18,6 +18,8 @@
<module>spring-cloud-tencent-featureenv-plugin</module>
<module>spring-cloud-tencent-gateway-plugin</module>
<module>spring-cloud-starter-tencent-discovery-adapter-plugin</module>
<module>spring-cloud-starter-tencent-tsf-adapter-plugin</module>
</modules>
</project>

@ -21,7 +21,7 @@ package com.tencent.cloud.plugin.discovery.adapter.config;
import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer;
import com.tencent.cloud.polaris.router.config.ConditionalOnPolarisRouterEnabled;
import com.tencent.cloud.polaris.router.config.LoadBalancerConfiguration;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

@ -18,7 +18,7 @@
package com.tencent.cloud.plugin.discovery.adapter.transformer;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.pojo.DefaultInstance;
import org.apache.commons.lang.StringUtils;

@ -19,7 +19,7 @@
package com.tencent.cloud.plugin.discovery.adapter.config;
import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer;
import com.tencent.cloud.polaris.router.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-tencent-plugin-starters</artifactId>
<groupId>com.tencent.cloud</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-starter-tencent-tsf-adapter-plugin</artifactId>
<name>Spring Cloud Starter Tencent TSF Plugin</name>
<dependencies>
<!-- Spring Cloud Tencent dependencies start -->
<dependency>
<groupId>com.tencent.cloud</groupId>
<artifactId>spring-cloud-tencent-rpc-enhancement</artifactId>
</dependency>
<!-- Spring Cloud Tencent dependencies end -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,47 @@
/*
* 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.tsf.adapter.config;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration;
import com.tencent.polaris.api.exception.PolarisException;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* PolarisTsfAdapterAutoConfiguration.
*
* @author sean yu
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnPolarisEnabled
@AutoConfigureAfter(RpcEnhancementAutoConfiguration.class)
public class PolarisTsfAdapterAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PolarisTsfFlowConfigModifier polarisFlowConfigModifier() throws PolarisException {
return new PolarisTsfFlowConfigModifier();
}
}

@ -15,29 +15,32 @@
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement.resttemplate;
package com.tencent.cloud.tsf.adapter.config;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.tencent.cloud.common.constant.ContextConstant;
import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import com.tencent.polaris.factory.config.ConfigurationImpl;
/**
* Intercept for BlockingLoadBalancerClient, put host and port to thread local.
* PolarisTsfFlowConfigModifier.
*
* @author lepdou 2022-09-05
* @author sean yu
*/
@Aspect
public class BlockingLoadBalancerClientAspect {
public class PolarisTsfFlowConfigModifier implements PolarisConfigModifier {
@Pointcut("execution(public * org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.reconstructURI(..)) ")
public void pointcut() {
/**
* Polaris Tsf Flow Name.
*/
public static final String TSF_FLOW_NAME = "tsf";
@Override
public void modify(ConfigurationImpl configuration) {
configuration.getGlobal().getSystem().getFlow().setName(TSF_FLOW_NAME);
}
@Around("pointcut()")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint);
return joinPoint.proceed();
@Override
public int getOrder() {
return ContextConstant.ModifierOrder.FIRST;
}
}

@ -0,0 +1,48 @@
/*
* 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.tsf.adapter.config;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* PolarisTsfAdapterAutoConfigurationTest.
*
* @author sean yu
*/
public class PolarisTsfAdapterAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
PolarisContextAutoConfiguration.class,
PolarisTsfAdapterAutoConfiguration.class
));
@Test
public void testDefaultInitialization() {
this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(PolarisTsfFlowConfigModifier.class);
});
}
}

@ -0,0 +1,38 @@
/*
* 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.tsf.adapter.config;
import com.tencent.polaris.assembly.flow.AssemblyFlow;
import com.tencent.polaris.client.api.SDKContext;
/**
* TsfAssemblyFlow.
*
* @author sean yu
*/
public class TsfAssemblyFlow implements AssemblyFlow {
@Override
public String getName() {
return PolarisTsfFlowConfigModifier.TSF_FLOW_NAME;
}
@Override
public void setSDKContext(SDKContext sdkContext) {
}
}

@ -0,0 +1,40 @@
/*
* 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.tsf.adapter.config;
import com.tencent.polaris.api.flow.DiscoveryFlow;
import com.tencent.polaris.client.api.SDKContext;
/**
* TsfDiscoveryFlow.
*
* @author sean yu
*/
public class TsfDiscoveryFlow implements DiscoveryFlow {
@Override
public String getName() {
return PolarisTsfFlowConfigModifier.TSF_FLOW_NAME;
}
@Override
public void setSDKContext(SDKContext sdkContext) {
}
}

@ -0,0 +1,39 @@
/*
* 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.tsf.adapter.config;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.router.api.flow.RouterFlow;
/**
* TsfRouterFlow.
*
* @author sean yu
*/
public class TsfRouterFlow implements RouterFlow {
@Override
public String getName() {
return PolarisTsfFlowConfigModifier.TSF_FLOW_NAME;
}
@Override
public void setSDKContext(SDKContext sdkContext) {
}
}

@ -99,6 +99,11 @@
<groupId>com.tencent.polaris</groupId>
<artifactId>loadbalancer-ringhash</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-assembly-factory</artifactId>
</dependency>
<!-- Polaris dependencies end -->
<dependency>

@ -27,6 +27,8 @@ import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.factory.AssemblyAPIFactory;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import com.tencent.polaris.factory.api.RouterAPIFactory;
@ -73,6 +75,11 @@ public class PolarisContextAutoConfiguration {
return RouterAPIFactory.createRouterAPIByContext(polarisContext);
}
@Bean
public AssemblyAPI assemblyAPI(SDKContext polarisContext) throws PolarisException {
return AssemblyAPIFactory.createAssemblyAPIByContext(polarisContext);
}
@Bean
@ConditionalOnMissingBean
public ModifyAddress polarisConfigModifier(PolarisContextProperties properties) {

@ -71,7 +71,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>

@ -20,20 +20,33 @@ package com.tencent.cloud.rpc.enhancement.config;
import java.util.Collections;
import java.util.List;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor;
import com.tencent.cloud.rpc.enhancement.feign.PolarisLoadBalancerFeignRequestTransformer;
import com.tencent.cloud.rpc.enhancement.filter.EnhancedReactiveFilter;
import com.tencent.cloud.rpc.enhancement.filter.EnhancedServletFilter;
import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.cloud.rpc.enhancement.resttemplate.BlockingLoadBalancerClientAspect;
import com.tencent.cloud.rpc.enhancement.resttemplate.EnhancedRestTemplateInterceptor;
import com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer;
import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter;
import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientReporter;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.cloud.rpc.enhancement.transformer.PolarisInstanceTransformer;
import com.tencent.cloud.rpc.enhancement.webclient.EnhancedWebClientExchangeFilterFunction;
import com.tencent.cloud.rpc.enhancement.webclient.PolarisLoadBalancerClientRequestTransformer;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.SmartInitializingSingleton;
@ -44,15 +57,25 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.Order;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import static jakarta.servlet.DispatcherType.ASYNC;
import static jakarta.servlet.DispatcherType.ERROR;
import static jakarta.servlet.DispatcherType.FORWARD;
import static jakarta.servlet.DispatcherType.INCLUDE;
import static jakarta.servlet.DispatcherType.REQUEST;
/**
* Auto Configuration for Polaris {@link feign.Feign} OR {@link RestTemplate} which can automatically bring in the call
* results for reporting.
@ -67,23 +90,92 @@ import org.springframework.web.reactive.function.client.WebClient;
public class RpcEnhancementAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(PolarisServiceInstance.class)
public InstanceTransformer instanceTransformer() {
return new PolarisInstanceTransformer();
}
@Bean
@Lazy
public EnhancedPluginRunner enhancedFeignPluginRunner(
@Autowired(required = false) List<EnhancedPlugin> enhancedPlugins) {
return new DefaultEnhancedPluginRunner(enhancedPlugins);
@Autowired(required = false) List<EnhancedPlugin> enhancedPlugins,
@Autowired(required = false) Registration registration,
SDKContext sdkContext) {
return new DefaultEnhancedPluginRunner(enhancedPlugins, registration, sdkContext);
}
@Bean
public SuccessPolarisReporter successPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
ConsumerAPI consumerAPI) {
return new SuccessPolarisReporter(properties, context, consumerAPI);
return new SuccessPolarisReporter(properties, consumerAPI);
}
@Bean
public ExceptionPolarisReporter exceptionPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
ConsumerAPI consumerAPI) {
return new ExceptionPolarisReporter(properties, context, consumerAPI);
return new ExceptionPolarisReporter(properties, consumerAPI);
}
@Bean
public AssemblyClientExceptionHook assemblyClientExceptionHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) {
return new AssemblyClientExceptionHook(assemblyAPI, instanceTransformer);
}
@Bean
public AssemblyClientPostHook assemblyClientPostHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) {
return new AssemblyClientPostHook(assemblyAPI, instanceTransformer);
}
@Bean
public AssemblyClientPreHook assemblyClientPreHook(AssemblyAPI assemblyAPI) {
return new AssemblyClientPreHook(assemblyAPI);
}
@Bean
public AssemblyServerExceptionHook assemblyServerExceptionHook(AssemblyAPI assemblyAPI) {
return new AssemblyServerExceptionHook(assemblyAPI);
}
@Bean
public AssemblyServerPostHook assemblyServerPostHook(AssemblyAPI assemblyAPI) {
return new AssemblyServerPostHook(assemblyAPI);
}
@Bean
public AssemblyServerPreHook assemblyServerPreHook(AssemblyAPI assemblyAPI) {
return new AssemblyServerPreHook(assemblyAPI);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
protected static class RpcEnhancementServletFilterConfig {
@Bean
public FilterRegistrationBean<EnhancedServletFilter> enhancedServletFilterRegistrationBean(
EnhancedServletFilter enhancedServletFilter) {
FilterRegistrationBean<EnhancedServletFilter> filterRegistrationBean =
new FilterRegistrationBean<>(enhancedServletFilter);
filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST);
filterRegistrationBean.setOrder(enhancedServletFilter.getClass().getAnnotation(Order.class).value());
return filterRegistrationBean;
}
@Bean
public EnhancedServletFilter enhancedServletFilter(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedServletFilter(pluginRunner);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
protected static class RpcEnhancementReactiveFilterConfig {
@Bean
public EnhancedReactiveFilter enhancedReactiveFilter(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedReactiveFilter(pluginRunner);
}
}
/**
@ -103,6 +195,13 @@ public class RpcEnhancementAutoConfiguration {
return new EnhancedFeignBeanPostProcessor(pluginRunner);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer"})
public PolarisLoadBalancerFeignRequestTransformer polarisLoadBalancerFeignRequestTransformer() {
return new PolarisLoadBalancerFeignRequestTransformer();
}
}
/**
@ -135,9 +234,9 @@ public class RpcEnhancementAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient"})
public BlockingLoadBalancerClientAspect blockingLoadBalancerClientAspect() {
return new BlockingLoadBalancerClientAspect();
@ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"})
public PolarisLoadBalancerRequestTransformer polarisLoadBalancerRequestTransformer() {
return new PolarisLoadBalancerRequestTransformer();
}
}
@ -155,12 +254,12 @@ public class RpcEnhancementAutoConfiguration {
private List<WebClient.Builder> webClientBuilder = Collections.emptyList();
@Bean
public EnhancedWebClientReporter exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedWebClientReporter(pluginRunner);
public EnhancedWebClientExchangeFilterFunction exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedWebClientExchangeFilterFunction(pluginRunner);
}
@Bean
public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientReporter reporter) {
public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientExchangeFilterFunction reporter) {
return () -> webClientBuilder.forEach(webClient -> {
webClient.filter(reporter);
});

@ -27,6 +27,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer;
import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient;
/**
@ -63,7 +64,9 @@ public class EnhancedFeignBeanPostProcessor implements BeanPostProcessor, BeanFa
if (delegate != null) {
return new EnhancedFeignBlockingLoadBalancerClient(createPolarisFeignClient(delegate),
factory.getBean(BlockingLoadBalancerClient.class),
factory.getBean(LoadBalancerClientFactory.class));
factory.getBean(LoadBalancerClientFactory.class),
factory.getBeanProvider(LoadBalancerFeignRequestTransformer.class).stream().toList()
);
}
}
return createPolarisFeignClient((Client) bean);

@ -17,11 +17,14 @@
package com.tencent.cloud.rpc.enhancement.feign;
import java.util.List;
import feign.Client;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer;
/**
* Wrap for {@link FeignBlockingLoadBalancerClient}.
@ -31,7 +34,7 @@ import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalance
public class EnhancedFeignBlockingLoadBalancerClient extends FeignBlockingLoadBalancerClient {
public EnhancedFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory) {
super(delegate, loadBalancerClient, loadBalancerClientFactory);
LoadBalancerClientFactory loadBalancerClientFactory, List<LoadBalancerFeignRequestTransformer> transformers) {
super(delegate, loadBalancerClient, loadBalancerClientFactory, transformers);
}
}

@ -21,8 +21,10 @@ import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import feign.Client;
@ -30,14 +32,11 @@ import feign.Request;
import feign.Request.Options;
import feign.Response;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
import static feign.Util.checkNotNull;
/**
@ -66,13 +65,18 @@ public class EnhancedFeignClient implements Client {
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(requestHeaders)
.httpMethod(HttpMethod.resolve(request.httpMethod().name()))
.httpMethod(HttpMethod.valueOf(request.httpMethod().name()))
.url(url)
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
try {
Response response = delegate.execute(request, options);
@ -87,26 +91,20 @@ public class EnhancedFeignClient implements Client {
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(request.requestTemplate().feignTarget().name());
serviceInstance.setHost(url.getHost());
serviceInstance.setPort(url.getPort());
enhancedPluginContext.setServiceInstance(serviceInstance);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
return response;
}
catch (IOException origin) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(origin);
// Run exception enhanced feign plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
throw origin;
}
finally {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
}
}
}

@ -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.rpc.enhancement.feign;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import feign.Request;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* PolarisLoadBalancerFeignRequestTransformer.
*
* @author sean yu
*/
public class PolarisLoadBalancerFeignRequestTransformer implements LoadBalancerFeignRequestTransformer {
/**
* Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
* @param request request
* @param instance instance
* @return HttpRequest
*/
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
}
return request;
}
}

@ -0,0 +1,93 @@
/*
* 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.filter;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
/**
* EnhancedReactiveFilter.
*
* @author sean yu
*/
public class EnhancedReactiveFilter implements WebFilter, Ordered {
private final EnhancedPluginRunner pluginRunner;
public EnhancedReactiveFilter(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(exchange.getRequest().getHeaders())
.httpMethod(exchange.getRequest().getMethod())
.url(exchange.getRequest().getURI())
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
return chain.filter(exchange)
.doOnSuccess(v -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(exchange.getResponse().getRawStatusCode())
.httpHeaders(exchange.getResponse().getHeaders())
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.POST, enhancedPluginContext);
})
.doOnError(e -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext);
})
.doFinally(v -> {
// Run finally enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext);
});
}
@Override
public int getOrder() {
return MetadataConstant.OrderConstant.WEB_FILTER_ORDER + 1;
}
}

@ -0,0 +1,115 @@
/*
* 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.filter;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* EnhancedServletFilter.
*
* @author sean yu
*/
@Order(MetadataConstant.OrderConstant.WEB_FILTER_ORDER + 1)
public class EnhancedServletFilter extends OncePerRequestFilter {
private final EnhancedPluginRunner pluginRunner;
public EnhancedServletFilter(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
HttpHeaders requestHeaders = new HttpHeaders();
Enumeration<String> requestHeaderNames = request.getHeaderNames();
if (requestHeaderNames != null) {
while (requestHeaderNames.hasMoreElements()) {
String requestHeaderName = requestHeaderNames.nextElement();
requestHeaders.addAll(requestHeaderName, Collections.list(request.getHeaders(requestHeaderName)));
}
}
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(requestHeaders)
.httpMethod(HttpMethod.valueOf(request.getMethod()))
.url(URI.create(request.getRequestURL().toString()))
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
try {
filterChain.doFilter(request, response);
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
HttpHeaders responseHeaders = new HttpHeaders();
Collection<String> responseHeaderNames = response.getHeaderNames();
if (responseHeaderNames != null) {
for (String responseHeaderName : responseHeaderNames) {
responseHeaders.addAll(responseHeaderName, new ArrayList<>(response.getHeaders(responseHeaderName)));
}
}
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(response.getStatus())
.httpHeaders(responseHeaders)
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.POST, enhancedPluginContext);
}
catch (ServletException | IOException e) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext);
throw e;
}
finally {
// Run finally enhanced plugins.
pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext);
}
}
}

@ -23,7 +23,12 @@ import java.util.List;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.client.api.SDKContext;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.util.CollectionUtils;
/**
@ -33,13 +38,28 @@ import org.springframework.util.CollectionUtils;
*/
public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
private final Multimap<String, EnhancedPlugin> pluginMap = ArrayListMultimap.create();
private final Multimap<EnhancedPluginType, EnhancedPlugin> pluginMap = ArrayListMultimap.create();
public DefaultEnhancedPluginRunner(List<EnhancedPlugin> enhancedPlugins) {
private final ServiceInstance localServiceInstance;
public DefaultEnhancedPluginRunner(
List<EnhancedPlugin> enhancedPlugins,
Registration registration,
SDKContext sdkContext
) {
if (!CollectionUtils.isEmpty(enhancedPlugins)) {
enhancedPlugins.stream()
.sorted(Comparator.comparing(EnhancedPlugin::getOrder))
.forEach(plugin -> pluginMap.put(plugin.getType().name(), plugin));
.forEach(plugin -> pluginMap.put(plugin.getType(), plugin));
}
if (registration != null) {
localServiceInstance = registration;
}
else {
DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance();
defaultServiceInstance.setServiceId(MetadataContext.LOCAL_SERVICE);
defaultServiceInstance.setHost(sdkContext.getConfig().getGlobal().getAPI().getBindIP());
localServiceInstance = defaultServiceInstance;
}
}
@ -51,7 +71,7 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
*/
@Override
public void run(EnhancedPluginType pluginType, EnhancedPluginContext context) {
for (EnhancedPlugin plugin : pluginMap.get(pluginType.name())) {
for (EnhancedPlugin plugin : pluginMap.get(pluginType)) {
try {
plugin.run(context);
}
@ -60,4 +80,10 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner {
}
}
}
@Override
public ServiceInstance getLocalServiceInstance() {
return this.localServiceInstance;
}
}

@ -35,7 +35,12 @@ public class EnhancedPluginContext {
private long delay;
private ServiceInstance serviceInstance;
private ServiceInstance localServiceInstance;
/**
* targetServiceInstance only exist in a client runner type.
*/
private ServiceInstance targetServiceInstance;
public EnhancedRequestContext getRequest() {
return request;
@ -69,12 +74,20 @@ public class EnhancedPluginContext {
this.delay = delay;
}
public ServiceInstance getServiceInstance() {
return serviceInstance;
public ServiceInstance getLocalServiceInstance() {
return localServiceInstance;
}
public void setLocalServiceInstance(ServiceInstance localServiceInstance) {
this.localServiceInstance = localServiceInstance;
}
public void setServiceInstance(ServiceInstance serviceInstance) {
this.serviceInstance = serviceInstance;
public ServiceInstance getTargetServiceInstance() {
return targetServiceInstance;
}
public void setTargetServiceInstance(ServiceInstance targetServiceInstance) {
this.targetServiceInstance = targetServiceInstance;
}
@Override
@ -84,7 +97,9 @@ public class EnhancedPluginContext {
", response=" + response +
", throwable=" + throwable +
", delay=" + delay +
", serviceInstance=" + serviceInstance +
", localServiceInstance=" + localServiceInstance +
", targetServiceInstance=" + targetServiceInstance +
'}';
}
}

@ -18,6 +18,8 @@
package com.tencent.cloud.rpc.enhancement.plugin;
import org.springframework.cloud.client.ServiceInstance;
/**
* Plugin runner.
*
@ -32,4 +34,7 @@ public interface EnhancedPluginRunner {
* @param context context in enhanced feign client.
*/
void run(EnhancedPluginType pluginType, EnhancedPluginContext context);
ServiceInstance getLocalServiceInstance();
}

@ -22,25 +22,52 @@ package com.tencent.cloud.rpc.enhancement.plugin;
*
* @author Haotian Zhang
*/
public enum EnhancedPluginType {
public interface EnhancedPluginType {
enum Client implements EnhancedPluginType {
/**
* Pre feign plugin.
* Pre Client plugin.
*/
PRE,
/**
* Post feign plugin.
* Post Client plugin.
*/
POST,
/**
* Exception feign plugin.
* Exception Client plugin.
*/
EXCEPTION,
/**
* Finally feign plugin.
* Finally Client plugin.
*/
FINALLY
}
enum Server implements EnhancedPluginType {
/**
* Pre Server plugin.
*/
PRE,
/**
* Post Server plugin.
*/
POST,
/**
* Exception Server plugin.
*/
EXCEPTION,
/**
* Finally Server plugin.
*/
FINALLY
}
}

@ -0,0 +1,67 @@
/*
* 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.plugin;
import org.springframework.core.Ordered;
/**
* PluginOrderConstant.
*
* @author sean yu
*/
public class PluginOrderConstant {
public static class ClientPluginOrder {
/**
* order for
* {@link com.tencent.cloud.polaris.circuitbreaker.reporter.SuccessCircuitBreakerReporter}
* and
* {@link com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter}.
*/
public static final int CONSUMER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
/**
* order for
* {@link com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter}.
*/
public static final int CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 2;
/**
* order for
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook}.
*/
public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 3;
}
public static class ServerPluginOrder {
/**
* order for
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook}
* and
* {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook}.
*/
public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
}
}

@ -15,7 +15,7 @@
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement;
package com.tencent.cloud.rpc.enhancement.plugin;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
@ -24,12 +24,18 @@ import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.constant.RouterConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.RequestLabelUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
@ -39,11 +45,11 @@ import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
@ -63,30 +69,21 @@ import static org.springframework.http.HttpStatus.SERVICE_UNAVAILABLE;
import static org.springframework.http.HttpStatus.VARIANT_ALSO_NEGOTIATES;
/**
* Abstract Polaris Reporter Adapter .
* Abstract Polaris Plugin Adapter .
*
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-11
*/
public abstract class AbstractPolarisReporterAdapter {
private static final Logger LOG = LoggerFactory.getLogger(AbstractPolarisReporterAdapter.class);
private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
public final class PolarisEnhancedPluginUtils {
protected final RpcEnhancementReporterProperties reportProperties;
private PolarisEnhancedPluginUtils() {
protected final SDKContext context;
/**
* Constructor With {@link RpcEnhancementReporterProperties} .
*
* @param reportProperties instance of {@link RpcEnhancementReporterProperties}.
*/
protected AbstractPolarisReporterAdapter(RpcEnhancementReporterProperties reportProperties, SDKContext context) {
this.reportProperties = reportProperties;
this.context = context;
}
private static final Logger LOG = LoggerFactory.getLogger(PolarisEnhancedPluginUtils.class);
private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
/**
* createServiceCallResult.
* @param calleeServiceName will pick up url host when null
@ -100,7 +97,7 @@ public abstract class AbstractPolarisReporterAdapter {
* @param exception exception
* @return ServiceCallResult
*/
public ServiceCallResult createServiceCallResult(
public static ServiceCallResult createServiceCallResult(String callerHost,
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, HttpHeaders requestHeaders, @Nullable HttpHeaders responseHeaders,
@Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
@ -112,11 +109,11 @@ public abstract class AbstractPolarisReporterAdapter {
resultRequest.setRetCode(statusCode == null ? -1 : statusCode);
resultRequest.setDelay(delay);
resultRequest.setCallerService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE));
resultRequest.setCallerIp(this.context.getConfig().getGlobal().getAPI().getBindIP());
resultRequest.setCallerIp(callerHost);
resultRequest.setHost(StringUtils.isBlank(calleeHost) ? uri.getHost() : calleeHost);
resultRequest.setPort(calleePort == null ? getPort(uri) : calleePort);
resultRequest.setLabels(getLabels(requestHeaders));
resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, getDefaultRetStatus(statusCode, exception)));
resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, statusCode, exception));
resultRequest.setRuleName(getActiveRuleNameFromRequest(responseHeaders));
return resultRequest;
}
@ -132,7 +129,7 @@ public abstract class AbstractPolarisReporterAdapter {
* @param exception exception
* @return ResourceStat
*/
public ResourceStat createInstanceResourceStat(
public static ResourceStat createInstanceResourceStat(
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
ServiceKey calleeServiceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, StringUtils.isBlank(calleeServiceName) ? uri.getHost() : calleeServiceName);
@ -165,14 +162,20 @@ public abstract class AbstractPolarisReporterAdapter {
* @param httpStatus request http status code
* @return true , otherwise return false .
*/
protected boolean apply(@Nullable HttpStatus httpStatus) {
static boolean apply(@Nullable HttpStatus httpStatus) {
if (Objects.isNull(httpStatus)) {
return false;
}
else {
RpcEnhancementReporterProperties reportProperties;
try {
reportProperties = ApplicationContextAwareUtils.getApplicationContext().getBean(RpcEnhancementReporterProperties.class);
}
catch (BeansException e) {
LOG.error("get RpcEnhancementReporterProperties bean err", e);
reportProperties = new RpcEnhancementReporterProperties();
}
// statuses > series
List<HttpStatus> status = reportProperties.getStatuses();
if (status.isEmpty()) {
List<HttpStatus.Series> series = reportProperties.getSeries();
// Check INTERNAL_SERVER_ERROR (500) status.
@ -182,25 +185,17 @@ public abstract class AbstractPolarisReporterAdapter {
if (series.isEmpty()) {
return HTTP_STATUSES.contains(httpStatus);
}
else {
try {
return series.contains(HttpStatus.Series.valueOf(httpStatus));
}
catch (Exception e) {
LOG.warn("Decode http status failed.", e);
}
return series.contains(httpStatus.series());
}
}
else {
// Use the user-specified fuse status code.
return status.contains(httpStatus);
}
}
// DEFAULT RETURN FALSE.
return false;
public static RetStatus getRetStatusFromRequest(HttpHeaders headers, Integer statusCode, Throwable exception) {
return getRetStatusFromRequest(headers, getDefaultRetStatus(statusCode, exception));
}
protected RetStatus getRetStatusFromRequest(HttpHeaders headers, RetStatus defaultVal) {
static RetStatus getRetStatusFromRequest(HttpHeaders headers, RetStatus defaultVal) {
if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_CALLEE_RET_STATUS)) {
List<String> values = headers.get(HeaderConstant.INTERNAL_CALLEE_RET_STATUS);
if (CollectionUtils.isNotEmpty(values)) {
@ -216,7 +211,7 @@ public abstract class AbstractPolarisReporterAdapter {
return defaultVal;
}
protected String getActiveRuleNameFromRequest(HttpHeaders headers) {
static String getActiveRuleNameFromRequest(HttpHeaders headers) {
if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) {
Collection<String> values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME);
if (CollectionUtils.isNotEmpty(values)) {
@ -226,7 +221,7 @@ public abstract class AbstractPolarisReporterAdapter {
return "";
}
private RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) {
private static RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) {
RetStatus retStatus = RetStatus.RetSuccess;
if (exception != null) {
retStatus = RetStatus.RetFail;
@ -240,12 +235,12 @@ public abstract class AbstractPolarisReporterAdapter {
return retStatus;
}
private int getPort(URI uri) {
private static int getPort(URI uri) {
// -1 means access directly by url, and use http default port number 80
return uri.getPort() == -1 ? 80 : uri.getPort();
}
private String getLabels(HttpHeaders headers) {
private static String getLabels(HttpHeaders headers) {
if (headers != null) {
Collection<String> labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER);
if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) {
@ -262,5 +257,27 @@ public abstract class AbstractPolarisReporterAdapter {
return null;
}
public static Map<String, String> getLabelMap(HttpHeaders headers) {
if (headers != null) {
Collection<String> labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER);
if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) {
String label = labels.iterator().next();
try {
label = URLDecoder.decode(label, UTF_8);
}
catch (UnsupportedEncodingException e) {
LOG.error("unsupported charset exception " + UTF_8, e);
}
try {
return new ObjectMapper().readValue(label, new TypeReference<HashMap<String, String>>() { });
}
catch (JsonProcessingException e) {
LOG.error("parse label map exception", e);
}
}
}
return null;
}
}

@ -0,0 +1,56 @@
/*
* 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.plugin.assembly;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.MetadataProvider;
import org.springframework.cloud.client.ServiceInstance;
/**
* AssemblyMetadataProvider.
*
* @author sean yu
*/
public class AssemblyMetadataProvider implements MetadataProvider {
private final ServiceInstance serviceInstance;
private final String namespace;
public AssemblyMetadataProvider(ServiceInstance localServiceInstance, String namespace) {
this.serviceInstance = localServiceInstance;
this.namespace = namespace;
}
@Override
public String getMetadata(String key) {
return serviceInstance.getMetadata().get(key);
}
@Override
public ServiceKey getLocalService() {
return new ServiceKey(namespace, serviceInstance.getServiceId());
}
@Override
public String getLocalIp() {
return serviceInstance.getHost();
}
}

@ -0,0 +1,125 @@
/*
* 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.plugin.assembly;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.google.common.net.HttpHeaders;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.RequestContext;
import org.springframework.http.HttpMethod;
/**
* AssemblyRequestContext.
*
* @author sean yu
*/
public class AssemblyRequestContext implements RequestContext {
private final EnhancedRequestContext requestContext;
private final ServiceKey callerService;
private final String callerIp;
private final Map<String, String> cookies;
public AssemblyRequestContext(EnhancedRequestContext requestContext, ServiceKey callerService, String callerIp) {
this.requestContext = requestContext;
this.callerService = callerService;
this.callerIp = callerIp;
this.cookies = new HashMap<>();
List<String> allCookies =
Optional.ofNullable(requestContext.getHttpHeaders().get(HttpHeaders.COOKIE))
.orElse(new ArrayList<>())
.stream()
.flatMap(it -> Arrays.stream(it.split(";")))
.toList();
allCookies.forEach(cookie -> {
String[] cookieKV = cookie.split("=");
if (cookieKV.length == 2) {
cookies.put(cookieKV[0], cookieKV[1]);
}
});
}
@Override
public String getMethod() {
return requestContext.getHttpMethod().name();
}
@Override
public void setMethod(String method) {
requestContext.setHttpMethod(HttpMethod.valueOf(method));
}
@Override
public String getHeader(String key) {
return requestContext.getHttpHeaders().getFirst(key);
}
@Override
public void setHeader(String key, String value) {
requestContext.getHttpHeaders().set(key, value);
}
@Override
public Collection<String> listHeaderKeys() {
return requestContext.getHttpHeaders().keySet();
}
@Override
public String getCookie(String key) {
return this.cookies.get(key);
}
@Override
public void setCookie(String key, String value) {
this.cookies.put(key, value);
}
@Override
public Collection<String> listCookieKeys() {
return this.cookies.keySet();
}
@Override
public String getCallerIp() {
return callerIp;
}
@Override
public ServiceKey getCallerService() {
return callerService;
}
@Override
public URI getURI() {
return requestContext.getUrl();
}
}

@ -0,0 +1,87 @@
/*
* 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.plugin.assembly;
import java.util.Collection;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.rpc.ResponseContext;
import org.springframework.lang.Nullable;
/**
* AssemblyResponseContext.
*
* @author sean yu
*/
public class AssemblyResponseContext implements ResponseContext {
private final EnhancedResponseContext responseContext;
private final Throwable throwable;
private final RetStatus retStatus;
public AssemblyResponseContext(@Nullable EnhancedResponseContext responseContext, @Nullable Throwable throwable) {
this.responseContext = responseContext;
this.throwable = throwable;
if (responseContext == null) {
this.retStatus = PolarisEnhancedPluginUtils.getRetStatusFromRequest(null, null, throwable);
}
else {
this.retStatus = PolarisEnhancedPluginUtils.getRetStatusFromRequest(responseContext.getHttpHeaders(), responseContext.getHttpStatus(), throwable);
}
}
@Override
public Object getRetCode() {
if (responseContext == null) {
return null;
}
return this.responseContext.getHttpStatus();
}
@Override
public String getHeader(String key) {
if (responseContext == null) {
return null;
}
return this.responseContext.getHttpHeaders().getFirst(key);
}
@Override
public Collection<String> listHeaders() {
if (responseContext == null) {
return null;
}
return this.responseContext.getHttpHeaders().keySet();
}
@Override
public Throwable getThrowable() {
return this.throwable;
}
@Override
public RetStatus getRetStatus() {
return this.retStatus;
}
}

@ -0,0 +1,82 @@
/*
* 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.plugin.assembly.client;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyClientExceptionHook.
*
* @author sean yu
*/
public class AssemblyClientExceptionHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
private final InstanceTransformer instanceTransformer;
public AssemblyClientExceptionHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) {
this.assemblyAPI = assemblyAPI;
this.instanceTransformer = instanceTransformer;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(null, context.getThrowable()));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
// TargetService and TargetInstance only exist in client side
afterRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId()));
afterRequest.setTargetInstance(instanceTransformer.transform(context.getTargetServiceInstance()));
assemblyAPI.afterCallService(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -0,0 +1,83 @@
/*
* 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.plugin.assembly.client;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyClientPostHook.
*
* @author sean yu
*/
public class AssemblyClientPostHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
private final InstanceTransformer instanceTransformer;
public AssemblyClientPostHook(AssemblyAPI assemblyAPI, InstanceTransformer instanceTransformer) {
this.assemblyAPI = assemblyAPI;
this.instanceTransformer = instanceTransformer;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.POST;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(context.getResponse(), null));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
// TargetService and TargetInstance only exist in client side
afterRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId()));
afterRequest.setTargetInstance(instanceTransformer.transform(context.getTargetServiceInstance()));
assemblyAPI.afterCallService(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -0,0 +1,73 @@
/*
* 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.plugin.assembly.client;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.BeforeRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyClientPreHook.
*
* @author sean yu
*/
public class AssemblyClientPreHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyClientPreHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Client.PRE;
}
@Override
public void run(EnhancedPluginContext context) {
BeforeRequest beforeRequest = new BeforeRequest();
beforeRequest.setCapabilities(new Capability[]{Capability.ALL});
beforeRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
beforeRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
// TargetService only exist in client side
beforeRequest.setTargetService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getTargetServiceInstance().getServiceId()));
assemblyAPI.beforeCallService(beforeRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -0,0 +1,76 @@
/*
* 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.plugin.assembly.server;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyServerExceptionHook.
*
* @author sean yu
*/
public class AssemblyServerExceptionHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyServerExceptionHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(null, context.getThrowable()));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
assemblyAPI.afterProcess(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -0,0 +1,75 @@
/*
* 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.plugin.assembly.server;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.AfterRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyServerPostHook.
*
* @author sean yu
*/
public class AssemblyServerPostHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyServerPostHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.POST;
}
@Override
public void run(EnhancedPluginContext context) {
AfterRequest afterRequest = new AfterRequest();
afterRequest.setCapabilities(new Capability[]{Capability.ALL});
afterRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
afterRequest.setResponseContext(new AssemblyResponseContext(context.getResponse(), null));
afterRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
afterRequest.setDelay(context.getDelay());
afterRequest.setRouteLabels(PolarisEnhancedPluginUtils.getLabelMap(context.getRequest().getHttpHeaders()));
assemblyAPI.afterProcess(afterRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -0,0 +1,70 @@
/*
* 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.plugin.assembly.server;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.assembly.api.pojo.BeforeRequest;
import com.tencent.polaris.assembly.api.pojo.Capability;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ServerPluginOrder.ASSEMBLY_PLUGIN_ORDER;
/**
* AssemblyServerPreHook.
*
* @author sean yu
*/
public class AssemblyServerPreHook implements EnhancedPlugin {
private final AssemblyAPI assemblyAPI;
public AssemblyServerPreHook(AssemblyAPI assemblyAPI) {
this.assemblyAPI = assemblyAPI;
}
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.Server.PRE;
}
@Override
public void run(EnhancedPluginContext context) {
BeforeRequest beforeRequest = new BeforeRequest();
beforeRequest.setCapabilities(new Capability[]{Capability.ALL});
beforeRequest.setRequestContext(new AssemblyRequestContext(
context.getRequest(),
new ServiceKey(MetadataContext.LOCAL_NAMESPACE, context.getLocalServiceInstance().getServiceId()),
context.getLocalServiceInstance().getHost()
));
beforeRequest.setMetadataProvider(new AssemblyMetadataProvider(context.getLocalServiceInstance(), MetadataContext.LOCAL_NAMESPACE));
assemblyAPI.beforeProcess(beforeRequest);
}
@Override
public int getOrder() {
return ASSEMBLY_PLUGIN_ORDER;
}
}

@ -20,37 +20,38 @@ package com.tencent.cloud.rpc.enhancement.plugin.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CONSUMER_REPORTER_PLUGIN_ORDER;
/**
* Polaris reporter when feign call fails.
*
* @author Haotian Zhang
*/
public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
public class ExceptionPolarisReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionPolarisReporter.class);
private final ConsumerAPI consumerAPI;
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reporterProperties,
SDKContext context,
private final RpcEnhancementReporterProperties reportProperties;
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reportProperties,
ConsumerAPI consumerAPI) {
super(reporterProperties, context);
this.reportProperties = reportProperties;
this.consumerAPI = consumerAPI;
}
@ -61,22 +62,24 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION;
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
public void run(EnhancedPluginContext context) {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = createServiceCallResult(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),
ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult(
callerServiceInstance.getHost(),
calleeServiceInstance.getServiceId(),
calleeServiceInstance.getHost(),
calleeServiceInstance.getPort(),
request.getUrl(),
request.getHttpHeaders(),
null,
@ -100,7 +103,7 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 1;
return CONSUMER_REPORTER_PLUGIN_ORDER;
}
}

@ -19,38 +19,39 @@ package com.tencent.cloud.rpc.enhancement.plugin.reporter;
import java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import com.tencent.cloud.rpc.enhancement.plugin.PolarisEnhancedPluginUtils;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
import static com.tencent.cloud.rpc.enhancement.plugin.PluginOrderConstant.ClientPluginOrder.CONSUMER_REPORTER_PLUGIN_ORDER;
/**
* Polaris reporter when feign call is successful.
*
* @author Haotian Zhang
*/
public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter implements EnhancedPlugin {
public class SuccessPolarisReporter implements EnhancedPlugin {
private static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final ConsumerAPI consumerAPI;
public SuccessPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
private final RpcEnhancementReporterProperties reportProperties;
public SuccessPolarisReporter(RpcEnhancementReporterProperties reportProperties,
ConsumerAPI consumerAPI) {
super(properties, context);
this.reportProperties = reportProperties;
this.consumerAPI = consumerAPI;
}
@ -61,23 +62,25 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.POST;
return EnhancedPluginType.Client.POST;
}
@Override
public void run(EnhancedPluginContext context) {
if (!super.reportProperties.isEnabled()) {
if (!this.reportProperties.isEnabled()) {
return;
}
EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = createServiceCallResult(
serviceInstance.getServiceId(),
serviceInstance.getHost(),
serviceInstance.getPort(),
ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult(
callerServiceInstance.getHost(),
calleeServiceInstance.getServiceId(),
calleeServiceInstance.getHost(),
calleeServiceInstance.getPort(),
request.getUrl(),
request.getHttpHeaders(),
response.getHttpHeaders(),
@ -101,6 +104,6 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 1;
return CONSUMER_REPORTER_PLUGIN_ORDER;
}
}

@ -18,25 +18,21 @@
package com.tencent.cloud.rpc.enhancement.resttemplate;
import java.io.IOException;
import java.util.Map;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* EnhancedRestTemplateInterceptor.
@ -63,8 +59,13 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis();
try {
ClientHttpResponse response = execution.execute(request, body);
@ -76,29 +77,20 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
Map<String, String> loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(request.getURI().getHost());
serviceInstance.setHost(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST));
if (loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT) != null) {
serviceInstance.setPort(Integer.parseInt(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT)));
}
enhancedPluginContext.setServiceInstance(serviceInstance);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
return response;
}
catch (IOException e) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
throw e;
}
finally {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
}
}

@ -17,28 +17,36 @@
package com.tencent.cloud.rpc.enhancement.resttemplate;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer;
import org.springframework.http.HttpRequest;
/**
* Extract load balancer result from {@link LoadBalancerClient} and put to MetadataContext.
* @author lepdou 2022-09-06
* PolarisLoadBalancerRequestTransformer.
*
* @author sean yu
*/
public final class LoadBalancerClientAspectUtils {
public class PolarisLoadBalancerRequestTransformer implements LoadBalancerRequestTransformer {
private LoadBalancerClientAspectUtils() {
}
/**
* LOAD_BALANCER_SERVICE_INSTANCE MetadataContext key.
*/
public static final String LOAD_BALANCER_SERVICE_INSTANCE = "LOAD_BALANCER_SERVICE_INSTANCE";
public static void extractLoadBalancerResult(ProceedingJoinPoint joinPoint) {
Object server = joinPoint.getArgs()[0];
if (server instanceof ServiceInstance) {
ServiceInstance instance = (ServiceInstance) server;
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST, instance.getHost());
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT, String.valueOf(instance.getPort()));
/**
* Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
* @param request request
* @param instance instance
* @return HttpRequest
*/
@Override
public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
}
return request;
}
}

@ -19,6 +19,7 @@ package com.tencent.cloud.rpc.enhancement.scg;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono;
@ -30,10 +31,6 @@ import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.PRE;
import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_LOADBALANCER_RESPONSE_ATTR;
@ -61,18 +58,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
// Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext);
long startTime = System.currentTimeMillis();
return chain.filter(exchange)
.doOnSubscribe(v -> {
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
Response<ServiceInstance> serviceInstanceResponse = exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR);
if (serviceInstanceResponse != null && serviceInstanceResponse.hasServer()) {
ServiceInstance instance = serviceInstanceResponse.getServer();
enhancedPluginContext.setServiceInstance(instance);
enhancedPluginContext.setTargetServiceInstance(instance);
}
})
// Run pre enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startTime = System.currentTimeMillis();
return chain.filter(exchange)
.doOnSuccess(v -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
@ -82,18 +79,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
})
.doOnError(t -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
enhancedPluginContext.setThrowable(t);
// Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
})
.doFinally(v -> {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
});
}

@ -16,7 +16,7 @@
*
*/
package com.tencent.cloud.polaris.router.spi;
package com.tencent.cloud.rpc.enhancement.transformer;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.pojo.DefaultInstance;

@ -16,10 +16,9 @@
*
*/
package com.tencent.cloud.polaris.router.transformer;
package com.tencent.cloud.rpc.enhancement.transformer;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.polaris.api.pojo.DefaultInstance;
import org.springframework.cloud.client.ServiceInstance;

@ -17,35 +17,31 @@
package com.tencent.cloud.rpc.enhancement.webclient;
import java.util.Map;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* EnhancedWebClientReporter.
* EnhancedWebClientExchangeFilterFunction.
*
* @author sean yu
*/
public class EnhancedWebClientReporter implements ExchangeFilterFunction {
public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFunction {
private final EnhancedPluginRunner pluginRunner;
public EnhancedWebClientReporter(EnhancedPluginRunner pluginRunner) {
public EnhancedWebClientExchangeFilterFunction(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner;
}
@ -60,38 +56,37 @@ public class EnhancedWebClientReporter implements ExchangeFilterFunction {
.build();
enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run post enhanced plugins.
pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startTime = System.currentTimeMillis();
return next.exchange(request)
.doOnSubscribe(subscription -> {
Map<String, String> loadBalancerContext = MetadataContextHolder.get().getLoadbalancerMetadata();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(loadBalancerContext.get(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID));
serviceInstance.setHost(request.url().getHost());
serviceInstance.setPort(request.url().getPort());
enhancedPluginContext.setServiceInstance(serviceInstance);
})
.doOnSuccess(response -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(response.rawStatusCode())
.httpStatus(response.statusCode().value())
.httpHeaders(response.headers().asHttpHeaders())
.build();
enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
})
.doOnError(t -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
enhancedPluginContext.setThrowable(t);
// Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
})
.doFinally(v -> {
// Run finally enhanced plugins.
pluginRunner.run(FINALLY, enhancedPluginContext);
pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
});
}
}

@ -17,13 +17,14 @@
package com.tencent.cloud.rpc.enhancement.webclient;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerClientRequestTransformer;
import org.springframework.web.reactive.function.client.ClientRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/**
* PolarisLoadBalancerClientRequestTransformer.
*
@ -31,10 +32,16 @@ import org.springframework.web.reactive.function.client.ClientRequest;
*/
public class PolarisLoadBalancerClientRequestTransformer implements LoadBalancerClientRequestTransformer {
/**
* Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
* @param request request
* @param instance instance
* @return HttpRequest
*/
@Override
public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) {
if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID, instance.getServiceId());
MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
}
return request;
}

@ -22,10 +22,12 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@ -63,6 +65,9 @@ public class EnhancedFeignBeanPostProcessorTest {
}
return null;
}).when(beanFactory).getBean(any(Class.class));
ObjectProvider objectProvider = mock(ObjectProvider.class);
doReturn(new PolarisLoadBalancerFeignRequestTransformer()).when(objectProvider).getObject();
doReturn(objectProvider).when(beanFactory).getBeanProvider(LoadBalancerFeignRequestTransformer.class);
enhancedFeignBeanPostProcessor.setBeanFactory(beanFactory);
// isNeedWrap(bean) == false

@ -30,6 +30,6 @@ public class EnhancedFeignBlockingLoadBalancerClientTest {
@Test
public void testConstructor() {
assertThatCode(() -> new EnhancedFeignBlockingLoadBalancerClient(null, null, null)).doesNotThrowAnyException();
assertThatCode(() -> new EnhancedFeignBlockingLoadBalancerClient(null, null, null, null)).doesNotThrowAnyException();
}
}

@ -26,6 +26,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.polaris.client.api.SDKContext;
import feign.Client;
import feign.Request;
import feign.RequestTemplate;
@ -34,6 +35,7 @@ import feign.Target;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ -55,6 +57,9 @@ import static org.mockito.Mockito.mock;
properties = {"spring.cloud.polaris.namespace=Test", "spring.cloud.polaris.service=TestApp", "spring.cloud.gateway.enabled=false"})
public class EnhancedFeignClientTest {
@Autowired
private SDKContext sdkContext;
@Test
public void testConstructor() {
try {
@ -75,7 +80,7 @@ public class EnhancedFeignClientTest {
List<EnhancedPlugin> enhancedPlugins = getMockEnhancedFeignPlugins();
try {
new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins));
new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins, null, sdkContext));
}
catch (Throwable e) {
fail("Exception encountered.", e);
@ -104,7 +109,7 @@ public class EnhancedFeignClientTest {
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.feignTarget(target);
EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins()));
EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), null, sdkContext));
// 200
Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test",
@ -134,7 +139,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.PRE;
return EnhancedPluginType.Client.PRE;
}
@Override
@ -156,7 +161,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.POST;
return EnhancedPluginType.Client.POST;
}
@Override
@ -178,7 +183,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION;
return EnhancedPluginType.Client.EXCEPTION;
}
@Override
@ -200,7 +205,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() {
@Override
public EnhancedPluginType getType() {
return EnhancedPluginType.FINALLY;
return EnhancedPluginType.Client.FINALLY;
}
@Override

@ -0,0 +1,94 @@
/*
* 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.feign;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import feign.Request;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.context.ApplicationContext;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* PolarisLoadBalancerFeignRequestTransformerTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class PolarisLoadBalancerFeignRequestTransformerTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private PolarisLoadBalancerFeignRequestTransformer transformer = new PolarisLoadBalancerFeignRequestTransformer();
@Mock
private Request clientRequest;
@Mock
private ServiceInstance serviceInstance;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
MetadataLocalProperties metadataLocalProperties = mock(MetadataLocalProperties.class);
StaticMetadataManager staticMetadataManager = mock(StaticMetadataManager.class);
doReturn(metadataLocalProperties).when(applicationContext).getBean(MetadataLocalProperties.class);
doReturn(staticMetadataManager).when(applicationContext).getBean(StaticMetadataManager.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext).thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void test() throws Throwable {
transformer.transformRequest(clientRequest, serviceInstance);
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance);
}
}

@ -0,0 +1,146 @@
/*
* 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.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyClientExceptionHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyClientExceptionHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyClientExceptionHook assemblyClientExceptionHook;
@Mock
private AssemblyAPI assemblyAPI;
@Mock
private InstanceTransformer instanceTransformer;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyClientExceptionHook.getName()).isEqualTo(AssemblyClientExceptionHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyClientExceptionHook.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyClientExceptionHook.run(pluginContext);
assemblyClientExceptionHook.getOrder();
assemblyClientExceptionHook.getName();
assemblyClientExceptionHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyClientExceptionHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -0,0 +1,146 @@
/*
* 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.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook;
import com.tencent.cloud.rpc.enhancement.transformer.InstanceTransformer;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyClientPostHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyClientPostHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyClientPostHook assemblyClientPostHook;
@Mock
private AssemblyAPI assemblyAPI;
@Mock
private InstanceTransformer instanceTransformer;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyClientPostHook.getName()).isEqualTo(AssemblyClientPostHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyClientPostHook.getType()).isEqualTo(EnhancedPluginType.Client.POST);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyClientPostHook.run(pluginContext);
assemblyClientPostHook.getOrder();
assemblyClientPostHook.getName();
assemblyClientPostHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyClientPostHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -0,0 +1,143 @@
/*
* 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.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyClientPreHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyClientPreHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyClientPreHook assemblyClientPreHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyClientPreHook.getName()).isEqualTo(AssemblyClientPreHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyClientPreHook.getType()).isEqualTo(EnhancedPluginType.Client.PRE);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyClientPreHook.run(pluginContext);
assemblyClientPreHook.getOrder();
assemblyClientPreHook.getName();
assemblyClientPreHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyClientPreHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -0,0 +1,57 @@
/*
* 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.plugin;
import java.util.HashMap;
import java.util.Map;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyMetadataProvider;
import com.tencent.polaris.api.pojo.ServiceKey;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.ServiceInstance;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
/**
* AssemblyMetadataProviderTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyMetadataProviderTest {
@Test
public void testAssemblyMetadataProvider() {
ServiceInstance serviceInstance = Mockito.mock(ServiceInstance.class);
Map<String, String> metadata = new HashMap<>() {{
put("k", "v");
}};
doReturn(metadata).when(serviceInstance).getMetadata();
doReturn("0.0.0.0").when(serviceInstance).getHost();
doReturn("test").when(serviceInstance).getServiceId();
AssemblyMetadataProvider assemblyMetadataProvider = new AssemblyMetadataProvider(serviceInstance, "test");
assertThat(assemblyMetadataProvider.getMetadata("k")).isEqualTo("v");
assertThat(assemblyMetadataProvider.getLocalIp()).isEqualTo("0.0.0.0");
assertThat(assemblyMetadataProvider.getLocalService()).isEqualTo(new ServiceKey("test", "test"));
}
}

@ -0,0 +1,83 @@
/*
* 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.plugin;
import java.net.URI;
import java.util.Arrays;
import java.util.HashSet;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyRequestContext;
import com.tencent.polaris.api.pojo.ServiceKey;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import static org.assertj.core.api.Assertions.assertThat;
/**
* AssemblyRequestContextTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyRequestContextTest {
@Test
public void testAssemblyRequestContext() {
URI uri = URI.create("http://0.0.0.0/");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("a", "a");
httpHeaders.add(HttpHeaders.COOKIE, "cookies-k1=cookies-v1;cookies-k2=cookies-v2");
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(uri)
.httpHeaders(httpHeaders)
.build();
ServiceKey callerService = new ServiceKey("test", "test");
AssemblyRequestContext assemblyRequestContext = new AssemblyRequestContext(
enhancedRequestContext,
callerService,
"0.0.0.0"
);
assertThat(assemblyRequestContext.getURI()).isEqualTo(uri);
assertThat(assemblyRequestContext.getHeader("a")).isEqualTo("a");
assemblyRequestContext.setHeader("b", "b");
assertThat(assemblyRequestContext.listHeaderKeys()).isEqualTo(new HashSet<>(Arrays.asList(HttpHeaders.COOKIE, "a", "b")));
assertThat(assemblyRequestContext.getMethod()).isEqualTo(HttpMethod.GET.toString());
assemblyRequestContext.setMethod(HttpMethod.OPTIONS.name());
assertThat(assemblyRequestContext.getMethod()).isEqualTo(HttpMethod.OPTIONS.toString());
assertThat(assemblyRequestContext.getCookie("cookies-k1")).isEqualTo("cookies-v1");
assertThat(assemblyRequestContext.getCookie("cookies-k2")).isEqualTo("cookies-v2");
assemblyRequestContext.setCookie("cookies-k3", "cookies-v3");
assertThat(assemblyRequestContext.listCookieKeys()).isEqualTo(new HashSet<>(Arrays.asList("cookies-k1", "cookies-k2", "cookies-k3")));
assertThat(assemblyRequestContext.getCallerService()).isEqualTo(callerService);
assertThat(assemblyRequestContext.getCallerIp()).isEqualTo("0.0.0.0");
}
}

@ -0,0 +1,101 @@
/*
* 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.plugin;
import java.net.SocketTimeoutException;
import java.util.HashSet;
import java.util.List;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.AssemblyResponseContext;
import com.tencent.polaris.api.pojo.RetStatus;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyResponseContextTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyResponseContextTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@Test
public void testAssemblyResponseContext() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("a", "a");
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpHeaders(httpHeaders)
.httpStatus(HttpStatus.OK.value())
.build();
AssemblyResponseContext assemblyResponseContext = new AssemblyResponseContext(enhancedResponseContext, null);
assertThat(assemblyResponseContext.getHeader("a")).isEqualTo("a");
assertThat(assemblyResponseContext.getRetCode()).isEqualTo(HttpStatus.OK.value());
assertThat(assemblyResponseContext.getThrowable()).isEqualTo(null);
assertThat(assemblyResponseContext.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
assertThat(assemblyResponseContext.listHeaders()).isEqualTo(new HashSet<>(List.of("a")));
Throwable e = new SocketTimeoutException();
assemblyResponseContext = new AssemblyResponseContext(null, e);
assertThat(assemblyResponseContext.getHeader("a")).isEqualTo(null);
assertThat(assemblyResponseContext.getRetCode()).isEqualTo(null);
assertThat(assemblyResponseContext.getThrowable()).isEqualTo(e);
assertThat(assemblyResponseContext.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
assertThat(assemblyResponseContext.listHeaders()).isEqualTo(null);
}
}

@ -0,0 +1,143 @@
/*
* 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.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyServerExceptionHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyServerExceptionHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyServerExceptionHook assemblyServerExceptionHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyServerExceptionHook.getName()).isEqualTo(AssemblyServerExceptionHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyServerExceptionHook.getType()).isEqualTo(EnhancedPluginType.Server.EXCEPTION);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyServerExceptionHook.run(pluginContext);
assemblyServerExceptionHook.getOrder();
assemblyServerExceptionHook.getName();
assemblyServerExceptionHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyServerExceptionHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -0,0 +1,143 @@
/*
* 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.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyServerPostHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyServerPostHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyServerPostHook assemblyServerPostHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyServerPostHook.getName()).isEqualTo(AssemblyServerPostHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyServerPostHook.getType()).isEqualTo(EnhancedPluginType.Server.POST);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyServerPostHook.run(pluginContext);
assemblyServerPostHook.getOrder();
assemblyServerPostHook.getName();
assemblyServerPostHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyServerPostHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -0,0 +1,143 @@
/*
* 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.plugin;
import java.net.URI;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
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.doReturn;
import static org.mockito.Mockito.mock;
/**
* AssemblyServerPreHookTest.
*
* @author sean yu
*/
@ExtendWith(MockitoExtension.class)
public class AssemblyServerPreHookTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@InjectMocks
private AssemblyServerPreHook assemblyServerPreHook;
@Mock
private AssemblyAPI assemblyAPI;
@BeforeAll
static void beforeAll() {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
static void afterAll() {
mockedApplicationContextAwareUtils.close();
}
@BeforeEach
void setUp() {
MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST;
MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER;
}
@Test
public void testGetName() {
assertThat(assemblyServerPreHook.getName()).isEqualTo(AssemblyServerPreHook.class.getName());
}
@Test
public void testType() {
assertThat(assemblyServerPreHook.getType()).isEqualTo(EnhancedPluginType.Server.PRE);
}
@Test
public void testRun() {
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance targetServiceInstance = new DefaultServiceInstance();
targetServiceInstance.setServiceId(SERVICE_PROVIDER);
DefaultServiceInstance localServiceInstance = new DefaultServiceInstance();
localServiceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setTargetServiceInstance(targetServiceInstance);
pluginContext.setLocalServiceInstance(localServiceInstance);
pluginContext.setThrowable(new RuntimeException());
assemblyServerPreHook.run(pluginContext);
assemblyServerPreHook.getOrder();
assemblyServerPreHook.getName();
assemblyServerPreHook.getType();
}
@Test
public void testHandlerThrowable() {
// mock request
EnhancedRequestContext request = mock(EnhancedRequestContext.class);
// mock response
EnhancedResponseContext response = mock(EnhancedResponseContext.class);
EnhancedPluginContext context = new EnhancedPluginContext();
context.setRequest(request);
context.setResponse(response);
assemblyServerPreHook.handlerThrowable(context, new RuntimeException("Mock exception."));
}
}

@ -25,6 +25,9 @@ import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll;
@ -38,6 +41,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@ -65,6 +69,8 @@ public class EnhancedPluginContextTest {
private SDKContext sdkContext;
@Mock
private ConsumerAPI consumerAPI;
@Mock
private Registration registration;
@BeforeAll
static void beforeAll() {
@ -111,24 +117,38 @@ public class EnhancedPluginContextTest {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
enhancedPluginContext.setRequest(requestContext);
enhancedPluginContext.setResponse(responseContext);
enhancedPluginContext.setServiceInstance(new DefaultServiceInstance());
enhancedPluginContext.setTargetServiceInstance(new DefaultServiceInstance());
enhancedPluginContext.setThrowable(mock(Exception.class));
enhancedPluginContext.setDelay(0);
assertThat(enhancedPluginContext.getRequest()).isNotNull();
assertThat(enhancedPluginContext.getResponse()).isNotNull();
assertThat(enhancedPluginContext.getServiceInstance()).isNotNull();
assertThat(enhancedPluginContext.getTargetServiceInstance()).isNotNull();
assertThat(enhancedPluginContext.getThrowable()).isNotNull();
assertThat(enhancedPluginContext.getDelay()).isNotNull();
EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, sdkContext, consumerAPI);
EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, sdkContext, consumerAPI);
EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1));
enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext);
EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, consumerAPI);
EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, consumerAPI);
EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1), registration, sdkContext);
enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
assertThat(enhancedPluginRunner.getLocalServiceInstance()).isEqualTo(registration);
EnhancedPlugin enhancedPlugin2 = mock(EnhancedPlugin.class);
doThrow(new RuntimeException()).when(enhancedPlugin2).run(any());
doReturn(EnhancedPluginType.POST).when(enhancedPlugin2).getType();
enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2));
enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext);
doReturn(EnhancedPluginType.Client.POST).when(enhancedPlugin2).getType();
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2), null, sdkContext);
enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
}
}

@ -23,11 +23,7 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -40,6 +36,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@ -63,8 +60,6 @@ public class ExceptionPolarisReporterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
private RpcEnhancementReporterProperties reporterProperties;
@Mock
private SDKContext sdkContext;
@InjectMocks
private ExceptionPolarisReporter exceptionPolarisReporter;
@Mock
@ -75,6 +70,12 @@ public class ExceptionPolarisReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -95,7 +96,7 @@ public class ExceptionPolarisReporterTest {
@Test
public void testType() {
assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION);
assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
}
@Test
@ -107,32 +108,23 @@ public class ExceptionPolarisReporterTest {
doReturn(true).when(reporterProperties).isEnabled();
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders())
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
pluginContext.setThrowable(new RuntimeException());
exceptionPolarisReporter.run(pluginContext);

@ -15,20 +15,19 @@
* specific language governing permissions and limitations under the License.
*/
package com.tencent.cloud.rpc.enhancement;
package com.tencent.cloud.rpc.enhancement.plugin;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.constant.RouterConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.rpc.ServiceCallResult;
@ -43,6 +42,7 @@ import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@ -54,12 +54,12 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
/**
* Test For {@link AbstractPolarisReporterAdapter}.
* Test For {@link PolarisEnhancedPluginUtils}.
*
* @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022/7/11
*/
@ExtendWith(MockitoExtension.class)
public class AbstractPolarisReporterAdapterTest {
public class PolarisEnhancedPluginUtilsTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private final RpcEnhancementReporterProperties reporterProperties = new RpcEnhancementReporterProperties();
@ -71,6 +71,12 @@ public class AbstractPolarisReporterAdapterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -86,25 +92,18 @@ public class AbstractPolarisReporterAdapterTest {
@Test
public void testServiceCallResult() throws URISyntaxException {
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext);
ServiceCallResult serviceCallResult;
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add(RouterConstant.ROUTER_LABEL_HEADER, "{\"k1\":\"v1\"}");
serviceCallResult = adapter.createServiceCallResult(
assertThat(PolarisEnhancedPluginUtils.getLabelMap(requestHeaders)).isEqualTo(new HashMap<String, String>() {{
put("k1", "v1");
}});
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
null,
null,
@ -117,7 +116,8 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
serviceCallResult = adapter.createServiceCallResult(
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
null,
null,
@ -130,7 +130,8 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetFail);
serviceCallResult = adapter.createServiceCallResult(
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
null,
null,
@ -143,7 +144,8 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
serviceCallResult = adapter.createServiceCallResult(
serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test",
"0.0.0.0",
8080,
@ -162,11 +164,9 @@ public class AbstractPolarisReporterAdapterTest {
@Test
public void testResourceStat() throws URISyntaxException {
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext);
ResourceStat resourceStat;
resourceStat = adapter.createInstanceResourceStat("test",
resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null,
null,
new URI("http://0.0.0.0/"),
@ -176,7 +176,7 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
resourceStat = adapter.createInstanceResourceStat("test",
resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null,
null,
new URI("http://0.0.0.0/"),
@ -186,7 +186,7 @@ public class AbstractPolarisReporterAdapterTest {
);
assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
resourceStat = adapter.createInstanceResourceStat("test",
resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null,
null,
new URI("http://0.0.0.0/"),
@ -200,13 +200,32 @@ public class AbstractPolarisReporterAdapterTest {
@Test
public void testApplyWithDefaultConfig() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
// Mock Condition
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
public void testApplyWithHttpStatus() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
properties.setStatuses(Arrays.asList(HttpStatus.BAD_GATEWAY, HttpStatus.INTERNAL_SERVER_ERROR));
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(null)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -216,12 +235,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear();
properties.setIgnoreInternalServerError(false);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -231,12 +254,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear();
properties.setIgnoreInternalServerError(true);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -246,12 +273,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear();
properties.getSeries().clear();
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
}
@Test
@ -262,65 +293,46 @@ public class AbstractPolarisReporterAdapterTest {
properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
ApplicationContext applicationContext = mock(ApplicationContext.class);
doReturn(properties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
// Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
}
@Test
public void testGetRetStatusFromRequest() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
// Mock Condition
properties.getStatuses().clear();
properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
HttpHeaders headers = new HttpHeaders();
RetStatus ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail);
RetStatus ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetFail);
headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc());
ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail);
ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetFlowControl);
headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetReject.getDesc());
ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail);
ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetReject);
}
@Test
public void testGetActiveRuleNameFromRequest() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties();
// Mock Condition
properties.getStatuses().clear();
properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR);
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(properties, sdkContext);
HttpHeaders headers = new HttpHeaders();
String ruleName = adapter.getActiveRuleNameFromRequest(headers);
String ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo("");
headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, "mock_rule");
ruleName = adapter.getActiveRuleNameFromRequest(headers);
ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo("mock_rule");
}
/**
* Simple Polaris CircuitBreak Adapter Implements .
*/
public static class SimplePolarisReporterAdapter extends AbstractPolarisReporterAdapter {
protected SimplePolarisReporterAdapter(RpcEnhancementReporterProperties reportProperties, SDKContext context) {
super(reportProperties, context);
}
}
}

@ -23,11 +23,7 @@ import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.config.Configuration;
import com.tencent.polaris.api.config.global.APIConfig;
import com.tencent.polaris.api.config.global.GlobalConfig;
import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -40,6 +36,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
@ -60,8 +57,6 @@ import static org.mockito.Mockito.verify;
public class SuccessPolarisReporterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
private SDKContext sdkContext;
@Mock
private RpcEnhancementReporterProperties reporterProperties;
@InjectMocks
private SuccessPolarisReporter successPolarisReporter;
@ -73,6 +68,12 @@ public class SuccessPolarisReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
ApplicationContext applicationContext = mock(ApplicationContext.class);
RpcEnhancementReporterProperties reporterProperties = mock(RpcEnhancementReporterProperties.class);
doReturn(reporterProperties)
.when(applicationContext).getBean(RpcEnhancementReporterProperties.class);
mockedApplicationContextAwareUtils.when(ApplicationContextAwareUtils::getApplicationContext)
.thenReturn(applicationContext);
}
@AfterAll
@ -93,7 +94,7 @@ public class SuccessPolarisReporterTest {
@Test
public void testType() {
assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.POST);
assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST);
}
@Test
@ -105,31 +106,23 @@ public class SuccessPolarisReporterTest {
verify(context, times(0)).getRequest();
doReturn(true).when(reporterProperties).isEnabled();
APIConfig apiConfig = mock(APIConfig.class);
doReturn("0.0.0.0").when(apiConfig).getBindIP();
GlobalConfig globalConfig = mock(GlobalConfig.class);
doReturn(apiConfig).when(globalConfig).getAPI();
Configuration configuration = mock(Configuration.class);
doReturn(globalConfig).when(configuration).getGlobal();
doReturn(configuration).when(sdkContext).getConfig();
EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/"))
.build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200)
.build();
response.toString();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request);
pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance);
pluginContext.setTargetServiceInstance(serviceInstance);
successPolarisReporter.run(pluginContext);
successPolarisReporter.getOrder();

@ -40,6 +40,7 @@ import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@ -65,6 +66,8 @@ public class EnhancedRestTemplateInterceptorTest {
@Mock
private SDKContext sdkContext;
@Mock
Registration registration;
@Mock
private ClientHttpRequestExecution mockClientHttpRequestExecution;
@Mock
private ClientHttpResponse mockClientHttpResponse;
@ -109,7 +112,7 @@ public class EnhancedRestTemplateInterceptorTest {
doReturn(mockHttpHeaders).when(mockHttpRequest).getHeaders();
doReturn(mockClientHttpResponse).when(mockClientHttpRequestExecution).execute(mockHttpRequest, inputBody);
EnhancedRestTemplateInterceptor reporter = new EnhancedRestTemplateInterceptor(new DefaultEnhancedPluginRunner(new ArrayList<>()));
EnhancedRestTemplateInterceptor reporter = new EnhancedRestTemplateInterceptor(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
actualResult = reporter.intercept(mockHttpRequest, inputBody, mockClientHttpRequestExecution);
assertThat(actualResult).isEqualTo(mockClientHttpResponse);

@ -17,13 +17,11 @@
package com.tencent.cloud.rpc.enhancement.resttemplate;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -36,7 +34,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
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;
@ -45,13 +45,16 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
public class BlockingLoadBalancerClientAspectTest {
public class PolarisLoadBalancerRequestTransformerTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private PolarisLoadBalancerRequestTransformer transformer = new PolarisLoadBalancerRequestTransformer();
@Mock
private ProceedingJoinPoint proceedingJoinPoint;
private HttpRequest clientRequest;
private BlockingLoadBalancerClientAspect aspect = new BlockingLoadBalancerClientAspect();
@Mock
private ServiceInstance serviceInstance;
@BeforeAll
static void beforeAll() {
@ -79,14 +82,8 @@ public class BlockingLoadBalancerClientAspectTest {
@Test
public void test() throws Throwable {
ServiceInstance serviceInstance = mock(ServiceInstance.class);
doReturn("0.0.0.0").when(serviceInstance).getHost();
doReturn(80).when(serviceInstance).getPort();
doReturn(new Object[]{ serviceInstance }).when(proceedingJoinPoint).getArgs();
aspect.invoke(proceedingJoinPoint);
aspect.pointcut();
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST)).isEqualTo("0.0.0.0");
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT)).isEqualTo("80");
transformer.transformRequest(clientRequest, serviceInstance);
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance);
}
}

@ -41,6 +41,7 @@ import reactor.core.publisher.Mono;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
@ -66,6 +67,8 @@ public class EnhancedGatewayGlobalFilterTest {
@Mock
private SDKContext sdkContext;
@Mock
Registration registration;
@Mock
ServerWebExchange exchange;
@Mock
GatewayFilterChain chain;
@ -123,7 +126,7 @@ public class EnhancedGatewayGlobalFilterTest {
doReturn(request).when(exchange).getRequest();
doReturn(response).when(exchange).getResponse();
EnhancedGatewayGlobalFilter reporter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(new ArrayList<>()));
EnhancedGatewayGlobalFilter reporter = new EnhancedGatewayGlobalFilter(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
reporter.getOrder();
reporter.filter(exchange, chain).block();

@ -39,9 +39,11 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatusCode;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFunction;
@ -56,7 +58,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
public class EnhancedWebClientReporterTest {
public class EnhancedWebClientExchangeFilterFunctionTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock
@ -64,6 +66,8 @@ public class EnhancedWebClientReporterTest {
@Mock
private SDKContext sdkContext;
@Mock
private Registration registration;
@Mock
private ClientRequest clientRequest;
@Mock
private ExchangeFunction exchangeFunction;
@ -101,9 +105,10 @@ public class EnhancedWebClientReporterTest {
doReturn(HttpMethod.GET).when(clientRequest).method();
ClientResponse.Headers headers = mock(ClientResponse.Headers.class);
doReturn(headers).when(clientResponse).headers();
doReturn(HttpStatusCode.valueOf(200)).when(clientResponse).statusCode();
doReturn(Mono.just(clientResponse)).when(exchangeFunction).exchange(any());
EnhancedWebClientReporter reporter = new EnhancedWebClientReporter(new DefaultEnhancedPluginRunner(new ArrayList<>()));
EnhancedWebClientExchangeFilterFunction reporter = new EnhancedWebClientExchangeFilterFunction(new DefaultEnhancedPluginRunner(new ArrayList<>(), registration, null));
ClientResponse clientResponse1 = reporter.filter(clientRequest, exchangeFunction).block();
assertThat(clientResponse1).isEqualTo(clientResponse);

@ -17,7 +17,6 @@
package com.tencent.cloud.rpc.enhancement.webclient;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager;
@ -37,6 +36,7 @@ import org.springframework.cloud.client.ServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.web.reactive.function.client.ClientRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
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;
@ -83,8 +83,7 @@ public class PolarisLoadBalancerClientRequestTransformerTest {
@Test
public void test() throws Throwable {
doReturn("test").when(serviceInstance).getServiceId();
transformer.transformRequest(clientRequest, serviceInstance);
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID)).isEqualTo("test");
assertThat(MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE)).isEqualTo(serviceInstance);
}
}

Loading…
Cancel
Save