Feature: add AssemblyFlow to support tsf (#992)

pull/1000/head
Shanyou Yu (Sean Yu) 1 year 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: 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) - [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) - [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 @Bean
@ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class) @ConditionalOnMissingBean(SuccessCircuitBreakerReporter.class)
public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties, public SuccessCircuitBreakerReporter successCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
return new SuccessCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); return new SuccessCircuitBreakerReporter(properties, circuitBreakAPI);
} }
@Bean @Bean
@ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class) @ConditionalOnMissingBean(ExceptionCircuitBreakerReporter.class)
public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties, public ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter(RpcEnhancementReporterProperties properties,
SDKContext polarisContext, CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
return new ExceptionCircuitBreakerReporter(properties, polarisContext, circuitBreakAPI); return new ExceptionCircuitBreakerReporter(properties, circuitBreakAPI);
} }
@Bean @Bean

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

@ -19,32 +19,38 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter;
import java.util.Optional; 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.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; 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.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; 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 static final Logger LOG = LoggerFactory.getLogger(ExceptionCircuitBreakerReporter.class);
private final CircuitBreakAPI circuitBreakAPI; private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties, public ExceptionCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context); this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI; this.circuitBreakAPI = circuitBreakAPI;
} }
@ -55,19 +61,19 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION; return EnhancedPluginType.Client.EXCEPTION;
} }
@Override @Override
public void run(EnhancedPluginContext context) throws Throwable { public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) { if (!this.reportProperties.isEnabled()) {
return; return;
} }
EnhancedRequestContext request = context.getRequest(); 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.getServiceId(),
serviceInstance.getHost(), serviceInstance.getHost(),
serviceInstance.getPort(), serviceInstance.getPort(),
@ -92,6 +98,6 @@ public class ExceptionCircuitBreakerReporter extends AbstractPolarisReporterAdap
@Override @Override
public int getOrder() { 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 java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; 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.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; 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 static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final CircuitBreakAPI circuitBreakAPI; private final CircuitBreakAPI circuitBreakAPI;
private final RpcEnhancementReporterProperties reportProperties;
public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties, public SuccessCircuitBreakerReporter(RpcEnhancementReporterProperties reportProperties,
SDKContext context,
CircuitBreakAPI circuitBreakAPI) { CircuitBreakAPI circuitBreakAPI) {
super(reportProperties, context); this.reportProperties = reportProperties;
this.circuitBreakAPI = circuitBreakAPI; this.circuitBreakAPI = circuitBreakAPI;
} }
@ -58,19 +63,19 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.POST; return EnhancedPluginType.Client.POST;
} }
@Override @Override
public void run(EnhancedPluginContext context) throws Throwable { public void run(EnhancedPluginContext context) throws Throwable {
if (!super.reportProperties.isEnabled()) { if (!this.reportProperties.isEnabled()) {
return; return;
} }
EnhancedRequestContext request = context.getRequest(); EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse(); 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.getServiceId(),
serviceInstance.getHost(), serviceInstance.getHost(),
serviceInstance.getPort(), serviceInstance.getPort(),
@ -94,6 +99,6 @@ public class SuccessCircuitBreakerReporter extends AbstractPolarisReporterAdapte
@Override @Override
public int getOrder() { public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 2; return CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER;
} }
} }

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

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

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

@ -17,15 +17,25 @@
package com.tencent.cloud.polaris.loadbalancer; 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.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.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled; 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.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration; import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
/** /**
* Auto-configuration of loadbalancer for Polaris. * Auto-configuration of loadbalancer for Polaris.
@ -41,4 +51,23 @@ import org.springframework.context.annotation.Configuration;
@LoadBalancerClients(defaultConfiguration = PolarisLoadBalancerClientConfiguration.class) @LoadBalancerClients(defaultConfiguration = PolarisLoadBalancerClientConfiguration.class)
public class PolarisLoadBalancerAutoConfiguration { 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() { 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; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -36,10 +39,17 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
private final PolarisRegistration registration; private final PolarisRegistration registration;
public PolarisAutoServiceRegistration(ServiceRegistry<PolarisRegistration> serviceRegistry, private final AssemblyAPI assemblyAPI;
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) {
public PolarisAutoServiceRegistration(
ServiceRegistry<PolarisRegistration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration,
AssemblyAPI assemblyAPI
) {
super(serviceRegistry, autoServiceRegistrationProperties); super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration; this.registration = registration;
this.assemblyAPI = assemblyAPI;
} }
@Override @Override
@ -58,6 +68,9 @@ public class PolarisAutoServiceRegistration extends AbstractAutoServiceRegistrat
LOGGER.debug("Registration disabled."); LOGGER.debug("Registration disabled.");
return; return;
} }
if (assemblyAPI != null) {
assemblyAPI.initService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE));
}
super.register(); super.register();
} }

@ -114,6 +114,7 @@ public class PolarisServiceRegistry implements ServiceRegistry<PolarisRegistrati
instanceRegisterRequest.setMetadata(registration.getMetadata()); instanceRegisterRequest.setMetadata(registration.getMetadata());
instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol()); instanceRegisterRequest.setProtocol(polarisDiscoveryProperties.getProtocol());
instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion()); instanceRegisterRequest.setVersion(polarisDiscoveryProperties.getVersion());
instanceRegisterRequest.setInstanceId(polarisDiscoveryProperties.getInstanceId());
try { try {
ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI(); ProviderAPI providerClient = polarisDiscoveryHandler.getProviderAPI();
InstanceRegisterResponse instanceRegisterResponse; 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.consul.ConsulContextProperties;
import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties; import com.tencent.cloud.polaris.extend.nacos.NacosContextProperties;
import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties; import com.tencent.cloud.rpc.enhancement.stat.config.PolarisStatProperties;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -78,9 +79,13 @@ public class PolarisServiceRegistryAutoConfiguration {
@Bean @Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class) @ConditionalOnBean(AutoServiceRegistrationProperties.class)
public PolarisAutoServiceRegistration polarisAutoServiceRegistration(PolarisServiceRegistry registry, public PolarisAutoServiceRegistration polarisAutoServiceRegistration(
AutoServiceRegistrationProperties autoServiceRegistrationProperties, PolarisRegistration registration) { PolarisServiceRegistry registry,
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration); AutoServiceRegistrationProperties autoServiceRegistrationProperties,
PolarisRegistration registration,
@Autowired(required = false) AssemblyAPI assemblyAPI
) {
return new PolarisAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration, assemblyAPI);
} }
@Bean @Bean

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

@ -75,7 +75,7 @@ public class PolarisAutoServiceRegistrationTest {
doNothing().when(serviceRegistry).register(nullable(PolarisRegistration.class)); doNothing().when(serviceRegistry).register(nullable(PolarisRegistration.class));
polarisAutoServiceRegistration = polarisAutoServiceRegistration =
new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration); new PolarisAutoServiceRegistration(serviceRegistry, autoServiceRegistrationProperties, registration, null);
doReturn(environment).when(applicationContext).getEnvironment(); doReturn(environment).when(applicationContext).getEnvironment();
polarisAutoServiceRegistration.setApplicationContext(applicationContext); 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.pojo.PolarisServiceInstance;
import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.resttemplate.PolarisLoadBalancerRequest; 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.RouterRequestInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor; 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.ErrorCode;
import com.tencent.polaris.api.exception.PolarisException; import com.tencent.polaris.api.exception.PolarisException;
import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.Instance;

@ -24,7 +24,7 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.tencent.cloud.common.metadata.MetadataContext; 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.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances; 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.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier; 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.RouterRequestInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor; 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 com.tencent.polaris.router.api.core.RouterAPI;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 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.resttemplate.PolarisLoadBalancerRequest;
import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor;
import com.tencent.cloud.polaris.router.spi.RouterResponseInterceptor; 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.exception.PolarisException;
import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances; 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.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServiceInstance; import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; 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.DefaultInstance;
import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances; 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.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.polaris.router.PolarisRouterServiceInstanceListSupplier; 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 com.tencent.polaris.router.api.core.RouterAPI;
import org.junit.jupiter.api.Test; 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.pojo.PolarisServiceInstance;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; 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.DefaultInstance;
import com.tencent.polaris.api.pojo.Instance; import com.tencent.polaris.api.pojo.Instance;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;

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

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

@ -18,6 +18,8 @@
<module>spring-cloud-tencent-featureenv-plugin</module> <module>spring-cloud-tencent-featureenv-plugin</module>
<module>spring-cloud-tencent-gateway-plugin</module> <module>spring-cloud-tencent-gateway-plugin</module>
<module>spring-cloud-starter-tencent-discovery-adapter-plugin</module> <module>spring-cloud-starter-tencent-discovery-adapter-plugin</module>
<module>spring-cloud-starter-tencent-tsf-adapter-plugin</module>
</modules> </modules>
</project> </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.plugin.discovery.adapter.transformer.NacosInstanceTransformer;
import com.tencent.cloud.polaris.router.config.ConditionalOnPolarisRouterEnabled; import com.tencent.cloud.polaris.router.config.ConditionalOnPolarisRouterEnabled;
import com.tencent.cloud.polaris.router.config.LoadBalancerConfiguration; 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.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

@ -18,7 +18,7 @@
package com.tencent.cloud.plugin.discovery.adapter.transformer; 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 com.tencent.polaris.api.pojo.DefaultInstance;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;

@ -19,7 +19,7 @@
package com.tencent.cloud.plugin.discovery.adapter.config; package com.tencent.cloud.plugin.discovery.adapter.config;
import com.tencent.cloud.plugin.discovery.adapter.transformer.NacosInstanceTransformer; 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.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; 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. * 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 com.tencent.cloud.common.constant.ContextConstant;
import org.aspectj.lang.annotation.Around; import com.tencent.cloud.polaris.context.PolarisConfigModifier;
import org.aspectj.lang.annotation.Aspect; import com.tencent.polaris.factory.config.ConfigurationImpl;
import org.aspectj.lang.annotation.Pointcut;
/** /**
* Intercept for BlockingLoadBalancerClient, put host and port to thread local. * PolarisTsfFlowConfigModifier.
* *
* @author lepdou 2022-09-05 * @author sean yu
*/ */
@Aspect public class PolarisTsfFlowConfigModifier implements PolarisConfigModifier {
public class BlockingLoadBalancerClientAspect {
@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()") @Override
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable { public int getOrder() {
LoadBalancerClientAspectUtils.extractLoadBalancerResult(joinPoint); return ContextConstant.ModifierOrder.FIRST;
return joinPoint.proceed();
} }
} }

@ -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> <groupId>com.tencent.polaris</groupId>
<artifactId>loadbalancer-ringhash</artifactId> <artifactId>loadbalancer-ringhash</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.tencent.polaris</groupId>
<artifactId>polaris-assembly-factory</artifactId>
</dependency>
<!-- Polaris dependencies end --> <!-- Polaris dependencies end -->
<dependency> <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.ConsumerAPI;
import com.tencent.polaris.api.core.ProviderAPI; import com.tencent.polaris.api.core.ProviderAPI;
import com.tencent.polaris.api.exception.PolarisException; 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.client.api.SDKContext;
import com.tencent.polaris.factory.api.DiscoveryAPIFactory; import com.tencent.polaris.factory.api.DiscoveryAPIFactory;
import com.tencent.polaris.factory.api.RouterAPIFactory; import com.tencent.polaris.factory.api.RouterAPIFactory;
@ -73,6 +75,11 @@ public class PolarisContextAutoConfiguration {
return RouterAPIFactory.createRouterAPIByContext(polarisContext); return RouterAPIFactory.createRouterAPIByContext(polarisContext);
} }
@Bean
public AssemblyAPI assemblyAPI(SDKContext polarisContext) throws PolarisException {
return AssemblyAPIFactory.createAssemblyAPIByContext(polarisContext);
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ModifyAddress polarisConfigModifier(PolarisContextProperties properties) { public ModifyAddress polarisConfigModifier(PolarisContextProperties properties) {

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

@ -20,20 +20,33 @@ package com.tencent.cloud.rpc.enhancement.config;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import com.tencent.cloud.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
import com.tencent.cloud.rpc.enhancement.feign.EnhancedFeignBeanPostProcessor; 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.DefaultEnhancedPluginRunner;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; 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.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; 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.EnhancedRestTemplateInterceptor;
import com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer;
import com.tencent.cloud.rpc.enhancement.scg.EnhancedGatewayGlobalFilter; 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.cloud.rpc.enhancement.webclient.PolarisLoadBalancerClientRequestTransformer;
import com.tencent.polaris.api.core.ConsumerAPI; import com.tencent.polaris.api.core.ConsumerAPI;
import com.tencent.polaris.assembly.api.AssemblyAPI;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import org.springframework.beans.factory.SmartInitializingSingleton; 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.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 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.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Role; import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.Order;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient; 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 * Auto Configuration for Polaris {@link feign.Feign} OR {@link RestTemplate} which can automatically bring in the call
* results for reporting. * results for reporting.
@ -67,23 +90,92 @@ import org.springframework.web.reactive.function.client.WebClient;
public class RpcEnhancementAutoConfiguration { public class RpcEnhancementAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean
@ConditionalOnClass(PolarisServiceInstance.class)
public InstanceTransformer instanceTransformer() {
return new PolarisInstanceTransformer();
}
@Bean
@Lazy
public EnhancedPluginRunner enhancedFeignPluginRunner( public EnhancedPluginRunner enhancedFeignPluginRunner(
@Autowired(required = false) List<EnhancedPlugin> enhancedPlugins) { @Autowired(required = false) List<EnhancedPlugin> enhancedPlugins,
return new DefaultEnhancedPluginRunner(enhancedPlugins); @Autowired(required = false) Registration registration,
SDKContext sdkContext) {
return new DefaultEnhancedPluginRunner(enhancedPlugins, registration, sdkContext);
} }
@Bean @Bean
public SuccessPolarisReporter successPolarisReporter(RpcEnhancementReporterProperties properties, public SuccessPolarisReporter successPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
ConsumerAPI consumerAPI) { ConsumerAPI consumerAPI) {
return new SuccessPolarisReporter(properties, context, consumerAPI); return new SuccessPolarisReporter(properties, consumerAPI);
} }
@Bean @Bean
public ExceptionPolarisReporter exceptionPolarisReporter(RpcEnhancementReporterProperties properties, public ExceptionPolarisReporter exceptionPolarisReporter(RpcEnhancementReporterProperties properties,
SDKContext context,
ConsumerAPI consumerAPI) { 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); 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 @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnClass(name = {"org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient"}) @ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"})
public BlockingLoadBalancerClientAspect blockingLoadBalancerClientAspect() { public PolarisLoadBalancerRequestTransformer polarisLoadBalancerRequestTransformer() {
return new BlockingLoadBalancerClientAspect(); return new PolarisLoadBalancerRequestTransformer();
} }
} }
@ -155,12 +254,12 @@ public class RpcEnhancementAutoConfiguration {
private List<WebClient.Builder> webClientBuilder = Collections.emptyList(); private List<WebClient.Builder> webClientBuilder = Collections.emptyList();
@Bean @Bean
public EnhancedWebClientReporter exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) { public EnhancedWebClientExchangeFilterFunction exchangeFilterFunction(@Lazy EnhancedPluginRunner pluginRunner) {
return new EnhancedWebClientReporter(pluginRunner); return new EnhancedWebClientExchangeFilterFunction(pluginRunner);
} }
@Bean @Bean
public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientReporter reporter) { public SmartInitializingSingleton addEnhancedWebClientReporterForWebClient(EnhancedWebClientExchangeFilterFunction reporter) {
return () -> webClientBuilder.forEach(webClient -> { return () -> webClientBuilder.forEach(webClient -> {
webClient.filter(reporter); 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.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient; import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.loadbalancer.LoadBalancerFeignRequestTransformer;
import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient; import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient;
/** /**
@ -63,7 +64,9 @@ public class EnhancedFeignBeanPostProcessor implements BeanPostProcessor, BeanFa
if (delegate != null) { if (delegate != null) {
return new EnhancedFeignBlockingLoadBalancerClient(createPolarisFeignClient(delegate), return new EnhancedFeignBlockingLoadBalancerClient(createPolarisFeignClient(delegate),
factory.getBean(BlockingLoadBalancerClient.class), factory.getBean(BlockingLoadBalancerClient.class),
factory.getBean(LoadBalancerClientFactory.class)); factory.getBean(LoadBalancerClientFactory.class),
factory.getBeanProvider(LoadBalancerFeignRequestTransformer.class).stream().toList()
);
} }
} }
return createPolarisFeignClient((Client) bean); return createPolarisFeignClient((Client) bean);

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

@ -21,8 +21,10 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; 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.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; 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.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import feign.Client; import feign.Client;
@ -30,14 +32,11 @@ import feign.Request;
import feign.Request.Options; import feign.Request.Options;
import feign.Response; import feign.Response;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION; import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
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 feign.Util.checkNotNull; import static feign.Util.checkNotNull;
/** /**
@ -66,13 +65,18 @@ public class EnhancedFeignClient implements Client {
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(requestHeaders) .httpHeaders(requestHeaders)
.httpMethod(HttpMethod.resolve(request.httpMethod().name())) .httpMethod(HttpMethod.valueOf(request.httpMethod().name()))
.url(url) .url(url)
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run pre enhanced plugins. // Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis(); long startMillis = System.currentTimeMillis();
try { try {
Response response = delegate.execute(request, options); Response response = delegate.execute(request, options);
@ -87,26 +91,20 @@ public class EnhancedFeignClient implements Client {
.build(); .build();
enhancedPluginContext.setResponse(enhancedResponseContext); 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. // Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
return response; return response;
} }
catch (IOException origin) { catch (IOException origin) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(origin); enhancedPluginContext.setThrowable(origin);
// Run exception enhanced feign plugins. // Run exception enhanced feign plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
throw origin; throw origin;
} }
finally { finally {
// Run finally enhanced plugins. // 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.ArrayListMultimap;
import com.google.common.collect.Multimap; 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; import org.springframework.util.CollectionUtils;
/** /**
@ -33,13 +38,28 @@ import org.springframework.util.CollectionUtils;
*/ */
public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner { 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)) { if (!CollectionUtils.isEmpty(enhancedPlugins)) {
enhancedPlugins.stream() enhancedPlugins.stream()
.sorted(Comparator.comparing(EnhancedPlugin::getOrder)) .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 @Override
public void run(EnhancedPluginType pluginType, EnhancedPluginContext context) { public void run(EnhancedPluginType pluginType, EnhancedPluginContext context) {
for (EnhancedPlugin plugin : pluginMap.get(pluginType.name())) { for (EnhancedPlugin plugin : pluginMap.get(pluginType)) {
try { try {
plugin.run(context); 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 long delay;
private ServiceInstance serviceInstance; private ServiceInstance localServiceInstance;
/**
* targetServiceInstance only exist in a client runner type.
*/
private ServiceInstance targetServiceInstance;
public EnhancedRequestContext getRequest() { public EnhancedRequestContext getRequest() {
return request; return request;
@ -69,12 +74,20 @@ public class EnhancedPluginContext {
this.delay = delay; this.delay = delay;
} }
public ServiceInstance getServiceInstance() { public ServiceInstance getLocalServiceInstance() {
return serviceInstance; return localServiceInstance;
}
public void setLocalServiceInstance(ServiceInstance localServiceInstance) {
this.localServiceInstance = localServiceInstance;
} }
public void setServiceInstance(ServiceInstance serviceInstance) { public ServiceInstance getTargetServiceInstance() {
this.serviceInstance = serviceInstance; return targetServiceInstance;
}
public void setTargetServiceInstance(ServiceInstance targetServiceInstance) {
this.targetServiceInstance = targetServiceInstance;
} }
@Override @Override
@ -84,7 +97,9 @@ public class EnhancedPluginContext {
", response=" + response + ", response=" + response +
", throwable=" + throwable + ", throwable=" + throwable +
", delay=" + delay + ", delay=" + delay +
", serviceInstance=" + serviceInstance + ", localServiceInstance=" + localServiceInstance +
", targetServiceInstance=" + targetServiceInstance +
'}'; '}';
} }
} }

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

@ -22,25 +22,52 @@ package com.tencent.cloud.rpc.enhancement.plugin;
* *
* @author Haotian Zhang * @author Haotian Zhang
*/ */
public enum EnhancedPluginType { public interface EnhancedPluginType {
/** enum Client implements EnhancedPluginType {
* Pre feign plugin. /**
*/ * Pre Client plugin.
PRE, */
PRE,
/**
* Post feign plugin. /**
*/ * Post Client plugin.
POST, */
POST,
/**
* Exception feign plugin. /**
*/ * Exception Client plugin.
EXCEPTION, */
EXCEPTION,
/**
* Finally feign plugin. /**
*/ * Finally Client plugin.
FINALLY */
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. * 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.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
@ -24,12 +24,18 @@ import java.net.URLDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; 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.HeaderConstant;
import com.tencent.cloud.common.constant.RouterConstant; import com.tencent.cloud.common.constant.RouterConstant;
import com.tencent.cloud.common.metadata.MetadataContext; 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.common.util.RequestLabelUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.polaris.api.plugin.circuitbreaker.ResourceStat; 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.pojo.ServiceKey;
import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.client.api.SDKContext;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable; 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; 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 * @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022-07-11
*/ */
public abstract class AbstractPolarisReporterAdapter { public final class PolarisEnhancedPluginUtils {
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);
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. * createServiceCallResult.
* @param calleeServiceName will pick up url host when null * @param calleeServiceName will pick up url host when null
@ -100,7 +97,7 @@ public abstract class AbstractPolarisReporterAdapter {
* @param exception exception * @param exception exception
* @return ServiceCallResult * @return ServiceCallResult
*/ */
public ServiceCallResult createServiceCallResult( public static ServiceCallResult createServiceCallResult(String callerHost,
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort, @Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, HttpHeaders requestHeaders, @Nullable HttpHeaders responseHeaders, URI uri, HttpHeaders requestHeaders, @Nullable HttpHeaders responseHeaders,
@Nullable Integer statusCode, long delay, @Nullable Throwable exception) { @Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
@ -112,11 +109,11 @@ public abstract class AbstractPolarisReporterAdapter {
resultRequest.setRetCode(statusCode == null ? -1 : statusCode); resultRequest.setRetCode(statusCode == null ? -1 : statusCode);
resultRequest.setDelay(delay); resultRequest.setDelay(delay);
resultRequest.setCallerService(new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE)); 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.setHost(StringUtils.isBlank(calleeHost) ? uri.getHost() : calleeHost);
resultRequest.setPort(calleePort == null ? getPort(uri) : calleePort); resultRequest.setPort(calleePort == null ? getPort(uri) : calleePort);
resultRequest.setLabels(getLabels(requestHeaders)); resultRequest.setLabels(getLabels(requestHeaders));
resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, getDefaultRetStatus(statusCode, exception))); resultRequest.setRetStatus(getRetStatusFromRequest(responseHeaders, statusCode, exception));
resultRequest.setRuleName(getActiveRuleNameFromRequest(responseHeaders)); resultRequest.setRuleName(getActiveRuleNameFromRequest(responseHeaders));
return resultRequest; return resultRequest;
} }
@ -132,7 +129,7 @@ public abstract class AbstractPolarisReporterAdapter {
* @param exception exception * @param exception exception
* @return ResourceStat * @return ResourceStat
*/ */
public ResourceStat createInstanceResourceStat( public static ResourceStat createInstanceResourceStat(
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort, @Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) { URI uri, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
ServiceKey calleeServiceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, StringUtils.isBlank(calleeServiceName) ? uri.getHost() : calleeServiceName); ServiceKey calleeServiceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, StringUtils.isBlank(calleeServiceName) ? uri.getHost() : calleeServiceName);
@ -165,42 +162,40 @@ public abstract class AbstractPolarisReporterAdapter {
* @param httpStatus request http status code * @param httpStatus request http status code
* @return true , otherwise return false . * @return true , otherwise return false .
*/ */
protected boolean apply(@Nullable HttpStatus httpStatus) { static boolean apply(@Nullable HttpStatus httpStatus) {
if (Objects.isNull(httpStatus)) { if (Objects.isNull(httpStatus)) {
return false; return false;
} }
else { RpcEnhancementReporterProperties reportProperties;
// statuses > series try {
List<HttpStatus> status = reportProperties.getStatuses(); reportProperties = ApplicationContextAwareUtils.getApplicationContext().getBean(RpcEnhancementReporterProperties.class);
}
if (status.isEmpty()) { catch (BeansException e) {
List<HttpStatus.Series> series = reportProperties.getSeries(); LOG.error("get RpcEnhancementReporterProperties bean err", e);
// Check INTERNAL_SERVER_ERROR (500) status. reportProperties = new RpcEnhancementReporterProperties();
if (reportProperties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) { }
return false; // statuses > series
} List<HttpStatus> status = reportProperties.getStatuses();
if (series.isEmpty()) { if (status.isEmpty()) {
return HTTP_STATUSES.contains(httpStatus); List<HttpStatus.Series> series = reportProperties.getSeries();
} // Check INTERNAL_SERVER_ERROR (500) status.
else { if (reportProperties.isIgnoreInternalServerError() && Objects.equals(httpStatus, INTERNAL_SERVER_ERROR)) {
try { return false;
return series.contains(HttpStatus.Series.valueOf(httpStatus));
}
catch (Exception e) {
LOG.warn("Decode http status failed.", e);
}
}
} }
else { if (series.isEmpty()) {
// Use the user-specified fuse status code. return HTTP_STATUSES.contains(httpStatus);
return status.contains(httpStatus);
} }
return series.contains(httpStatus.series());
} }
// DEFAULT RETURN FALSE. // Use the user-specified fuse status code.
return false; return status.contains(httpStatus);
}
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)) { if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_CALLEE_RET_STATUS)) {
List<String> values = headers.get(HeaderConstant.INTERNAL_CALLEE_RET_STATUS); List<String> values = headers.get(HeaderConstant.INTERNAL_CALLEE_RET_STATUS);
if (CollectionUtils.isNotEmpty(values)) { if (CollectionUtils.isNotEmpty(values)) {
@ -216,7 +211,7 @@ public abstract class AbstractPolarisReporterAdapter {
return defaultVal; return defaultVal;
} }
protected String getActiveRuleNameFromRequest(HttpHeaders headers) { static String getActiveRuleNameFromRequest(HttpHeaders headers) {
if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) { if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) {
Collection<String> values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME); Collection<String> values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME);
if (CollectionUtils.isNotEmpty(values)) { if (CollectionUtils.isNotEmpty(values)) {
@ -226,7 +221,7 @@ public abstract class AbstractPolarisReporterAdapter {
return ""; return "";
} }
private RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) { private static RetStatus getDefaultRetStatus(Integer statusCode, Throwable exception) {
RetStatus retStatus = RetStatus.RetSuccess; RetStatus retStatus = RetStatus.RetSuccess;
if (exception != null) { if (exception != null) {
retStatus = RetStatus.RetFail; retStatus = RetStatus.RetFail;
@ -240,12 +235,12 @@ public abstract class AbstractPolarisReporterAdapter {
return retStatus; 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 // -1 means access directly by url, and use http default port number 80
return uri.getPort() == -1 ? 80 : uri.getPort(); return uri.getPort() == -1 ? 80 : uri.getPort();
} }
private String getLabels(HttpHeaders headers) { private static String getLabels(HttpHeaders headers) {
if (headers != null) { if (headers != null) {
Collection<String> labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER); Collection<String> labels = headers.get(RouterConstant.ROUTER_LABEL_HEADER);
if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) { if (CollectionUtils.isNotEmpty(labels) && labels.iterator().hasNext()) {
@ -262,5 +257,27 @@ public abstract class AbstractPolarisReporterAdapter {
return null; 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 java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; 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.core.ConsumerAPI;
import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; 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. * Polaris reporter when feign call fails.
* *
* @author Haotian Zhang * @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 static final Logger LOG = LoggerFactory.getLogger(ExceptionPolarisReporter.class);
private final ConsumerAPI consumerAPI; private final ConsumerAPI consumerAPI;
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reporterProperties, private final RpcEnhancementReporterProperties reportProperties;
SDKContext context,
public ExceptionPolarisReporter(RpcEnhancementReporterProperties reportProperties,
ConsumerAPI consumerAPI) { ConsumerAPI consumerAPI) {
super(reporterProperties, context); this.reportProperties = reportProperties;
this.consumerAPI = consumerAPI; this.consumerAPI = consumerAPI;
} }
@ -61,22 +62,24 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION; return EnhancedPluginType.Client.EXCEPTION;
} }
@Override @Override
public void run(EnhancedPluginContext context) { public void run(EnhancedPluginContext context) {
if (!super.reportProperties.isEnabled()) { if (!this.reportProperties.isEnabled()) {
return; return;
} }
EnhancedRequestContext request = context.getRequest(); EnhancedRequestContext request = context.getRequest();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = createServiceCallResult(
serviceInstance.getServiceId(), ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult(
serviceInstance.getHost(), callerServiceInstance.getHost(),
serviceInstance.getPort(), calleeServiceInstance.getServiceId(),
calleeServiceInstance.getHost(),
calleeServiceInstance.getPort(),
request.getUrl(), request.getUrl(),
request.getHttpHeaders(), request.getHttpHeaders(),
null, null,
@ -100,7 +103,7 @@ public class ExceptionPolarisReporter extends AbstractPolarisReporterAdapter imp
@Override @Override
public int getOrder() { 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 java.util.Optional;
import com.tencent.cloud.rpc.enhancement.AbstractPolarisReporterAdapter;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; 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.core.ConsumerAPI;
import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.rpc.ServiceCallResult;
import com.tencent.polaris.client.api.SDKContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; 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. * Polaris reporter when feign call is successful.
* *
* @author Haotian Zhang * @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 static final Logger LOG = LoggerFactory.getLogger(SuccessPolarisReporter.class);
private final ConsumerAPI consumerAPI; private final ConsumerAPI consumerAPI;
public SuccessPolarisReporter(RpcEnhancementReporterProperties properties, private final RpcEnhancementReporterProperties reportProperties;
SDKContext context,
public SuccessPolarisReporter(RpcEnhancementReporterProperties reportProperties,
ConsumerAPI consumerAPI) { ConsumerAPI consumerAPI) {
super(properties, context); this.reportProperties = reportProperties;
this.consumerAPI = consumerAPI; this.consumerAPI = consumerAPI;
} }
@ -61,23 +62,25 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.POST; return EnhancedPluginType.Client.POST;
} }
@Override @Override
public void run(EnhancedPluginContext context) { public void run(EnhancedPluginContext context) {
if (!super.reportProperties.isEnabled()) { if (!this.reportProperties.isEnabled()) {
return; return;
} }
EnhancedRequestContext request = context.getRequest(); EnhancedRequestContext request = context.getRequest();
EnhancedResponseContext response = context.getResponse(); EnhancedResponseContext response = context.getResponse();
ServiceInstance serviceInstance = Optional.ofNullable(context.getServiceInstance()).orElse(new DefaultServiceInstance()); ServiceInstance callerServiceInstance = Optional.ofNullable(context.getLocalServiceInstance()).orElse(new DefaultServiceInstance());
ServiceInstance calleeServiceInstance = Optional.ofNullable(context.getTargetServiceInstance()).orElse(new DefaultServiceInstance());
ServiceCallResult resultRequest = createServiceCallResult(
serviceInstance.getServiceId(), ServiceCallResult resultRequest = PolarisEnhancedPluginUtils.createServiceCallResult(
serviceInstance.getHost(), callerServiceInstance.getHost(),
serviceInstance.getPort(), calleeServiceInstance.getServiceId(),
calleeServiceInstance.getHost(),
calleeServiceInstance.getPort(),
request.getUrl(), request.getUrl(),
request.getHttpHeaders(), request.getHttpHeaders(),
response.getHttpHeaders(), response.getHttpHeaders(),
@ -101,6 +104,6 @@ public class SuccessPolarisReporter extends AbstractPolarisReporterAdapter imple
@Override @Override
public int getOrder() { public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 1; return CONSUMER_REPORTER_PLUGIN_ORDER;
} }
} }

@ -18,25 +18,21 @@
package com.tencent.cloud.rpc.enhancement.resttemplate; package com.tencent.cloud.rpc.enhancement.resttemplate;
import java.io.IOException; 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.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; 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.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; 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.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.EXCEPTION; import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
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;
/** /**
* EnhancedRestTemplateInterceptor. * EnhancedRestTemplateInterceptor.
@ -63,8 +59,13 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
enhancedPluginContext.setTargetServiceInstance(
(ServiceInstance) MetadataContextHolder.get().getLoadbalancerMetadata().get(LOAD_BALANCER_SERVICE_INSTANCE));
// Run pre enhanced plugins. // Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startMillis = System.currentTimeMillis(); long startMillis = System.currentTimeMillis();
try { try {
ClientHttpResponse response = execution.execute(request, body); ClientHttpResponse response = execution.execute(request, body);
@ -76,29 +77,20 @@ public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterce
.build(); .build();
enhancedPluginContext.setResponse(enhancedResponseContext); 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. // Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
return response; return response;
} }
catch (IOException e) { catch (IOException e) {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis); enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
enhancedPluginContext.setThrowable(e); enhancedPluginContext.setThrowable(e);
// Run exception enhanced plugins. // Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
throw e; throw e;
} }
finally { finally {
// Run finally enhanced plugins. // 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; package com.tencent.cloud.rpc.enhancement.resttemplate;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.cloud.client.ServiceInstance; 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. * PolarisLoadBalancerRequestTransformer.
* @author lepdou 2022-09-06 *
* @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]; * Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
if (server instanceof ServiceInstance) { * @param request request
ServiceInstance instance = (ServiceInstance) server; * @param instance instance
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_HOST, instance.getHost()); * @return HttpRequest
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_INSTANCE_PORT, String.valueOf(instance.getPort())); */
@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.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; 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.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -30,10 +31,6 @@ import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange; 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.filter.ReactiveLoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_LOADBALANCER_RESPONSE_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_LOADBALANCER_RESPONSE_ATTR;
@ -61,18 +58,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setRequest(enhancedRequestContext);
enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
Response<ServiceInstance> serviceInstanceResponse = exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR);
if (serviceInstanceResponse != null && serviceInstanceResponse.hasServer()) {
ServiceInstance instance = serviceInstanceResponse.getServer();
enhancedPluginContext.setTargetServiceInstance(instance);
}
// Run pre enhanced plugins. // Run pre enhanced plugins.
pluginRunner.run(PRE, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
return chain.filter(exchange) return chain.filter(exchange)
.doOnSubscribe(v -> {
Response<ServiceInstance> serviceInstanceResponse = exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR);
if (serviceInstanceResponse != null && serviceInstanceResponse.hasServer()) {
ServiceInstance instance = serviceInstanceResponse.getServer();
enhancedPluginContext.setServiceInstance(instance);
}
})
.doOnSuccess(v -> { .doOnSuccess(v -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
@ -82,18 +79,18 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
enhancedPluginContext.setResponse(enhancedResponseContext); enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins. // Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
}) })
.doOnError(t -> { .doOnError(t -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
enhancedPluginContext.setThrowable(t); enhancedPluginContext.setThrowable(t);
// Run exception enhanced plugins. // Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
}) })
.doFinally(v -> { .doFinally(v -> {
// Run finally enhanced plugins. // 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.cloud.common.metadata.MetadataContext;
import com.tencent.polaris.api.pojo.DefaultInstance; 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.common.pojo.PolarisServiceInstance;
import com.tencent.cloud.polaris.router.spi.InstanceTransformer;
import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.pojo.DefaultInstance;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;

@ -17,35 +17,31 @@
package com.tencent.cloud.rpc.enhancement.webclient; 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.common.metadata.MetadataContextHolder;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; 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.EnhancedRequestContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext;
import reactor.core.publisher.Mono; 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.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction; 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.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.FINALLY;
import static com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType.POST;
/** /**
* EnhancedWebClientReporter. * EnhancedWebClientExchangeFilterFunction.
* *
* @author sean yu * @author sean yu
*/ */
public class EnhancedWebClientReporter implements ExchangeFilterFunction { public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFunction {
private final EnhancedPluginRunner pluginRunner; private final EnhancedPluginRunner pluginRunner;
public EnhancedWebClientReporter(EnhancedPluginRunner pluginRunner) { public EnhancedWebClientExchangeFilterFunction(EnhancedPluginRunner pluginRunner) {
this.pluginRunner = pluginRunner; this.pluginRunner = pluginRunner;
} }
@ -60,38 +56,37 @@ public class EnhancedWebClientReporter implements ExchangeFilterFunction {
.build(); .build();
enhancedPluginContext.setRequest(enhancedRequestContext); 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(); long startTime = System.currentTimeMillis();
return next.exchange(request) 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 -> { .doOnSuccess(response -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder() EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
.httpStatus(response.rawStatusCode()) .httpStatus(response.statusCode().value())
.httpHeaders(response.headers().asHttpHeaders()) .httpHeaders(response.headers().asHttpHeaders())
.build(); .build();
enhancedPluginContext.setResponse(enhancedResponseContext); enhancedPluginContext.setResponse(enhancedResponseContext);
// Run post enhanced plugins. // Run post enhanced plugins.
pluginRunner.run(POST, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
}) })
.doOnError(t -> { .doOnError(t -> {
enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime); enhancedPluginContext.setDelay(System.currentTimeMillis() - startTime);
enhancedPluginContext.setThrowable(t); enhancedPluginContext.setThrowable(t);
// Run exception enhanced plugins. // Run exception enhanced plugins.
pluginRunner.run(EXCEPTION, enhancedPluginContext); pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
}) })
.doFinally(v -> { .doFinally(v -> {
// Run finally enhanced plugins. // 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; package com.tencent.cloud.rpc.enhancement.webclient;
import com.tencent.cloud.common.constant.HeaderConstant;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerClientRequestTransformer; import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerClientRequestTransformer;
import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientRequest;
import static com.tencent.cloud.rpc.enhancement.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE;
/** /**
* PolarisLoadBalancerClientRequestTransformer. * PolarisLoadBalancerClientRequestTransformer.
* *
@ -31,10 +32,16 @@ import org.springframework.web.reactive.function.client.ClientRequest;
*/ */
public class PolarisLoadBalancerClientRequestTransformer implements LoadBalancerClientRequestTransformer { public class PolarisLoadBalancerClientRequestTransformer implements LoadBalancerClientRequestTransformer {
/**
* Transform Request, add Loadbalancer ServiceInstance to MetadataContext.
* @param request request
* @param instance instance
* @return HttpRequest
*/
@Override @Override
public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) { public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) {
if (instance != null) { if (instance != null) {
MetadataContextHolder.get().setLoadbalancer(HeaderConstant.INTERNAL_CALLEE_SERVICE_ID, instance.getServiceId()); MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance);
} }
return request; return request;
} }

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

@ -30,6 +30,6 @@ public class EnhancedFeignBlockingLoadBalancerClientTest {
@Test @Test
public void testConstructor() { 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.EnhancedPlugin;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext;
import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType;
import com.tencent.polaris.client.api.SDKContext;
import feign.Client; import feign.Client;
import feign.Request; import feign.Request;
import feign.RequestTemplate; import feign.RequestTemplate;
@ -34,6 +35,7 @@ import feign.Target;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension; 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"}) properties = {"spring.cloud.polaris.namespace=Test", "spring.cloud.polaris.service=TestApp", "spring.cloud.gateway.enabled=false"})
public class EnhancedFeignClientTest { public class EnhancedFeignClientTest {
@Autowired
private SDKContext sdkContext;
@Test @Test
public void testConstructor() { public void testConstructor() {
try { try {
@ -75,7 +80,7 @@ public class EnhancedFeignClientTest {
List<EnhancedPlugin> enhancedPlugins = getMockEnhancedFeignPlugins(); List<EnhancedPlugin> enhancedPlugins = getMockEnhancedFeignPlugins();
try { try {
new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins)); new EnhancedFeignClient(mock(Client.class), new DefaultEnhancedPluginRunner(enhancedPlugins, null, sdkContext));
} }
catch (Throwable e) { catch (Throwable e) {
fail("Exception encountered.", e); fail("Exception encountered.", e);
@ -104,7 +109,7 @@ public class EnhancedFeignClientTest {
RequestTemplate requestTemplate = new RequestTemplate(); RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.feignTarget(target); requestTemplate.feignTarget(target);
EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins())); EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), null, sdkContext));
// 200 // 200
Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test", Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test",
@ -134,7 +139,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() { enhancedPlugins.add(new EnhancedPlugin() {
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.PRE; return EnhancedPluginType.Client.PRE;
} }
@Override @Override
@ -156,7 +161,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() { enhancedPlugins.add(new EnhancedPlugin() {
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.POST; return EnhancedPluginType.Client.POST;
} }
@Override @Override
@ -178,7 +183,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() { enhancedPlugins.add(new EnhancedPlugin() {
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.EXCEPTION; return EnhancedPluginType.Client.EXCEPTION;
} }
@Override @Override
@ -200,7 +205,7 @@ public class EnhancedFeignClientTest {
enhancedPlugins.add(new EnhancedPlugin() { enhancedPlugins.add(new EnhancedPlugin() {
@Override @Override
public EnhancedPluginType getType() { public EnhancedPluginType getType() {
return EnhancedPluginType.FINALLY; return EnhancedPluginType.Client.FINALLY;
} }
@Override @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.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter; import com.tencent.cloud.rpc.enhancement.plugin.reporter.ExceptionPolarisReporter;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; 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.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
@ -38,6 +41,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
@ -65,6 +69,8 @@ public class EnhancedPluginContextTest {
private SDKContext sdkContext; private SDKContext sdkContext;
@Mock @Mock
private ConsumerAPI consumerAPI; private ConsumerAPI consumerAPI;
@Mock
private Registration registration;
@BeforeAll @BeforeAll
static void beforeAll() { static void beforeAll() {
@ -111,24 +117,38 @@ public class EnhancedPluginContextTest {
EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();
enhancedPluginContext.setRequest(requestContext); enhancedPluginContext.setRequest(requestContext);
enhancedPluginContext.setResponse(responseContext); enhancedPluginContext.setResponse(responseContext);
enhancedPluginContext.setServiceInstance(new DefaultServiceInstance()); enhancedPluginContext.setTargetServiceInstance(new DefaultServiceInstance());
enhancedPluginContext.setThrowable(mock(Exception.class)); enhancedPluginContext.setThrowable(mock(Exception.class));
enhancedPluginContext.setDelay(0); enhancedPluginContext.setDelay(0);
assertThat(enhancedPluginContext.getRequest()).isNotNull(); assertThat(enhancedPluginContext.getRequest()).isNotNull();
assertThat(enhancedPluginContext.getResponse()).isNotNull(); assertThat(enhancedPluginContext.getResponse()).isNotNull();
assertThat(enhancedPluginContext.getServiceInstance()).isNotNull(); assertThat(enhancedPluginContext.getTargetServiceInstance()).isNotNull();
assertThat(enhancedPluginContext.getThrowable()).isNotNull(); assertThat(enhancedPluginContext.getThrowable()).isNotNull();
assertThat(enhancedPluginContext.getDelay()).isNotNull(); assertThat(enhancedPluginContext.getDelay()).isNotNull();
EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, sdkContext, consumerAPI); EnhancedPlugin enhancedPlugin = new SuccessPolarisReporter(reporterProperties, consumerAPI);
EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, sdkContext, consumerAPI); EnhancedPlugin enhancedPlugin1 = new ExceptionPolarisReporter(reporterProperties, consumerAPI);
EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1)); EnhancedPluginRunner enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin, enhancedPlugin1), registration, sdkContext);
enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext); enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
assertThat(enhancedPluginRunner.getLocalServiceInstance()).isEqualTo(registration);
EnhancedPlugin enhancedPlugin2 = mock(EnhancedPlugin.class); EnhancedPlugin enhancedPlugin2 = mock(EnhancedPlugin.class);
doThrow(new RuntimeException()).when(enhancedPlugin2).run(any()); doThrow(new RuntimeException()).when(enhancedPlugin2).run(any());
doReturn(EnhancedPluginType.POST).when(enhancedPlugin2).getType(); doReturn(EnhancedPluginType.Client.POST).when(enhancedPlugin2).getType();
enhancedPluginRunner = new DefaultEnhancedPluginRunner(Arrays.asList(enhancedPlugin2));
enhancedPluginRunner.run(EnhancedPluginType.POST, enhancedPluginContext); 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.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; 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.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.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -40,6 +36,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
@ -63,8 +60,6 @@ public class ExceptionPolarisReporterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils; private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock @Mock
private RpcEnhancementReporterProperties reporterProperties; private RpcEnhancementReporterProperties reporterProperties;
@Mock
private SDKContext sdkContext;
@InjectMocks @InjectMocks
private ExceptionPolarisReporter exceptionPolarisReporter; private ExceptionPolarisReporter exceptionPolarisReporter;
@Mock @Mock
@ -75,6 +70,12 @@ public class ExceptionPolarisReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test"); .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 @AfterAll
@ -95,7 +96,7 @@ public class ExceptionPolarisReporterTest {
@Test @Test
public void testType() { public void testType() {
assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.EXCEPTION); assertThat(exceptionPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.EXCEPTION);
} }
@Test @Test
@ -107,32 +108,23 @@ public class ExceptionPolarisReporterTest {
doReturn(true).when(reporterProperties).isEnabled(); 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(); EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder() EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET) .httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/")) .url(URI.create("http://0.0.0.0/"))
.httpHeaders(new HttpHeaders()) .httpHeaders(new HttpHeaders())
.build(); .build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder() EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200) .httpStatus(200)
.build(); .build();
response.toString();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(SERVICE_PROVIDER); serviceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request); pluginContext.setRequest(request);
pluginContext.setResponse(response); pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance); pluginContext.setTargetServiceInstance(serviceInstance);
pluginContext.setThrowable(new RuntimeException()); pluginContext.setThrowable(new RuntimeException());
exceptionPolarisReporter.run(pluginContext); exceptionPolarisReporter.run(pluginContext);

@ -15,20 +15,19 @@
* specific language governing permissions and limitations under the License. * 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.SocketTimeoutException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; 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.HeaderConstant;
import com.tencent.cloud.common.constant.RouterConstant; import com.tencent.cloud.common.constant.RouterConstant;
import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; 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.plugin.circuitbreaker.ResourceStat;
import com.tencent.polaris.api.pojo.RetStatus; import com.tencent.polaris.api.pojo.RetStatus;
import com.tencent.polaris.api.rpc.ServiceCallResult; import com.tencent.polaris.api.rpc.ServiceCallResult;
@ -43,6 +42,7 @@ import org.mockito.MockedStatic;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -54,12 +54,12 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; 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 * @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a> 2022/7/11
*/ */
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class AbstractPolarisReporterAdapterTest { public class PolarisEnhancedPluginUtilsTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils; private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private final RpcEnhancementReporterProperties reporterProperties = new RpcEnhancementReporterProperties(); private final RpcEnhancementReporterProperties reporterProperties = new RpcEnhancementReporterProperties();
@ -71,6 +71,12 @@ public class AbstractPolarisReporterAdapterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test"); .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 @AfterAll
@ -86,25 +92,18 @@ public class AbstractPolarisReporterAdapterTest {
@Test @Test
public void testServiceCallResult() throws URISyntaxException { 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; ServiceCallResult serviceCallResult;
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add(RouterConstant.ROUTER_LABEL_HEADER, "{\"k1\":\"v1\"}"); 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", "test",
null, null,
null, null,
@ -117,7 +116,8 @@ public class AbstractPolarisReporterAdapterTest {
); );
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetSuccess); assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
serviceCallResult = adapter.createServiceCallResult( serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test", "test",
null, null,
null, null,
@ -130,7 +130,8 @@ public class AbstractPolarisReporterAdapterTest {
); );
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetFail); assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetFail);
serviceCallResult = adapter.createServiceCallResult( serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test", "test",
null, null,
null, null,
@ -143,7 +144,8 @@ public class AbstractPolarisReporterAdapterTest {
); );
assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetTimeout); assertThat(serviceCallResult.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
serviceCallResult = adapter.createServiceCallResult( serviceCallResult = PolarisEnhancedPluginUtils.createServiceCallResult(
"0.0.0.0",
"test", "test",
"0.0.0.0", "0.0.0.0",
8080, 8080,
@ -162,11 +164,9 @@ public class AbstractPolarisReporterAdapterTest {
@Test @Test
public void testResourceStat() throws URISyntaxException { public void testResourceStat() throws URISyntaxException {
SimplePolarisReporterAdapter adapter = new SimplePolarisReporterAdapter(reporterProperties, sdkContext);
ResourceStat resourceStat; ResourceStat resourceStat;
resourceStat = adapter.createInstanceResourceStat("test", resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null, null,
null, null,
new URI("http://0.0.0.0/"), new URI("http://0.0.0.0/"),
@ -176,7 +176,7 @@ public class AbstractPolarisReporterAdapterTest {
); );
assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetSuccess); assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetSuccess);
resourceStat = adapter.createInstanceResourceStat("test", resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null, null,
null, null,
new URI("http://0.0.0.0/"), new URI("http://0.0.0.0/"),
@ -186,7 +186,7 @@ public class AbstractPolarisReporterAdapterTest {
); );
assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetTimeout); assertThat(resourceStat.getRetStatus()).isEqualTo(RetStatus.RetTimeout);
resourceStat = adapter.createInstanceResourceStat("test", resourceStat = PolarisEnhancedPluginUtils.createInstanceResourceStat("test",
null, null,
null, null,
new URI("http://0.0.0.0/"), new URI("http://0.0.0.0/"),
@ -200,13 +200,32 @@ public class AbstractPolarisReporterAdapterTest {
@Test @Test
public void testApplyWithDefaultConfig() { public void testApplyWithDefaultConfig() {
RpcEnhancementReporterProperties properties = new RpcEnhancementReporterProperties(); 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 // Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(null)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
} }
@Test @Test
@ -216,12 +235,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear(); properties.getStatuses().clear();
properties.setIgnoreInternalServerError(false); 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 // Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(true);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
} }
@Test @Test
@ -231,12 +254,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear(); properties.getStatuses().clear();
properties.setIgnoreInternalServerError(true); 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 // Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
} }
@Test @Test
@ -246,12 +273,16 @@ public class AbstractPolarisReporterAdapterTest {
properties.getStatuses().clear(); properties.getStatuses().clear();
properties.getSeries().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 // Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(true);
} }
@Test @Test
@ -262,65 +293,46 @@ public class AbstractPolarisReporterAdapterTest {
properties.getSeries().clear(); properties.getSeries().clear();
properties.getSeries().add(HttpStatus.Series.CLIENT_ERROR); 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 // Assert
assertThat(adapter.apply(HttpStatus.OK)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.OK)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.INTERNAL_SERVER_ERROR)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.BAD_GATEWAY)).isEqualTo(false);
assertThat(adapter.apply(HttpStatus.FORBIDDEN)).isEqualTo(true); assertThat(PolarisEnhancedPluginUtils.apply(HttpStatus.FORBIDDEN)).isEqualTo(true);
} }
@Test @Test
public void testGetRetStatusFromRequest() { 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(); HttpHeaders headers = new HttpHeaders();
RetStatus ret = adapter.getRetStatusFromRequest(headers, RetStatus.RetFail); RetStatus ret = PolarisEnhancedPluginUtils.getRetStatusFromRequest(headers, RetStatus.RetFail);
assertThat(ret).isEqualTo(RetStatus.RetFail); assertThat(ret).isEqualTo(RetStatus.RetFail);
headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc()); 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); assertThat(ret).isEqualTo(RetStatus.RetFlowControl);
headers.set(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetReject.getDesc()); 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); assertThat(ret).isEqualTo(RetStatus.RetReject);
} }
@Test @Test
public void testGetActiveRuleNameFromRequest() { 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(); HttpHeaders headers = new HttpHeaders();
String ruleName = adapter.getActiveRuleNameFromRequest(headers); String ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo(""); assertThat(ruleName).isEqualTo("");
headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, "mock_rule"); headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, "mock_rule");
ruleName = adapter.getActiveRuleNameFromRequest(headers); ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo("mock_rule"); 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.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties;
import com.tencent.cloud.rpc.enhancement.plugin.reporter.SuccessPolarisReporter; 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.api.core.ConsumerAPI;
import com.tencent.polaris.client.api.SDKContext;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -40,6 +36,7 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
@ -60,8 +57,6 @@ import static org.mockito.Mockito.verify;
public class SuccessPolarisReporterTest { public class SuccessPolarisReporterTest {
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils; private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
@Mock @Mock
private SDKContext sdkContext;
@Mock
private RpcEnhancementReporterProperties reporterProperties; private RpcEnhancementReporterProperties reporterProperties;
@InjectMocks @InjectMocks
private SuccessPolarisReporter successPolarisReporter; private SuccessPolarisReporter successPolarisReporter;
@ -73,6 +68,12 @@ public class SuccessPolarisReporterTest {
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test"); .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 @AfterAll
@ -93,7 +94,7 @@ public class SuccessPolarisReporterTest {
@Test @Test
public void testType() { public void testType() {
assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.POST); assertThat(successPolarisReporter.getType()).isEqualTo(EnhancedPluginType.Client.POST);
} }
@Test @Test
@ -105,31 +106,23 @@ public class SuccessPolarisReporterTest {
verify(context, times(0)).getRequest(); verify(context, times(0)).getRequest();
doReturn(true).when(reporterProperties).isEnabled(); 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(); EnhancedPluginContext pluginContext = new EnhancedPluginContext();
EnhancedRequestContext request = EnhancedRequestContext.builder() EnhancedRequestContext request = EnhancedRequestContext.builder()
.httpMethod(HttpMethod.GET) .httpMethod(HttpMethod.GET)
.url(URI.create("http://0.0.0.0/")) .url(URI.create("http://0.0.0.0/"))
.build(); .build();
request.toString();
EnhancedResponseContext response = EnhancedResponseContext.builder() EnhancedResponseContext response = EnhancedResponseContext.builder()
.httpStatus(200) .httpStatus(200)
.build(); .build();
response.toString();
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); DefaultServiceInstance serviceInstance = new DefaultServiceInstance();
serviceInstance.setServiceId(SERVICE_PROVIDER); serviceInstance.setServiceId(SERVICE_PROVIDER);
pluginContext.setRequest(request); pluginContext.setRequest(request);
pluginContext.setResponse(response); pluginContext.setResponse(response);
pluginContext.setServiceInstance(serviceInstance); pluginContext.setTargetServiceInstance(serviceInstance);
successPolarisReporter.run(pluginContext); successPolarisReporter.run(pluginContext);
successPolarisReporter.getOrder(); successPolarisReporter.getOrder();

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

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

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

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

@ -17,7 +17,6 @@
package com.tencent.cloud.rpc.enhancement.webclient; 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.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.StaticMetadataManager; 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.context.ApplicationContext;
import org.springframework.web.reactive.function.client.ClientRequest; 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.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -83,8 +83,7 @@ public class PolarisLoadBalancerClientRequestTransformerTest {
@Test @Test
public void test() throws Throwable { public void test() throws Throwable {
doReturn("test").when(serviceInstance).getServiceId();
transformer.transformRequest(clientRequest, serviceInstance); 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