From 616c9f2358c5d58b58612a84d8defbdae24ce6d8 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Thu, 14 Aug 2025 17:32:46 +0800 Subject: [PATCH] fix: tsf related bugfixes (#1698) Co-authored-by: shedfreewu <49236872+shedfreewu@users.noreply.github.com> --- .licenserc.yaml | 2 +- CHANGELOG.md | 3 +- .../MetadataTransferAutoConfiguration.java | 68 +-------------- ...sferMedataRestTemplateEnhancedPlugin.java} | 41 +++++----- ... EnhancedRestTemplateInterceptorTest.java} | 7 +- .../extend/consul/ConsulDiscoveryUtil.java | 2 +- .../registry/PolarisServiceRegistry.java | 10 ++- .../cloud/polaris/router/RouterUtilsTest.java | 2 + .../common/constant/ContextConstant.java | 19 +++++ .../cloud/common/constant/OrderConstant.java | 6 +- .../common/metadata/MetadataContext.java | 4 + .../common/util/MetadataContextUtils.java | 49 +++++++++++ .../cloud/common/util/TsfTagUtils.java | 2 + .../gateway/context/ContextGatewayFilter.java | 22 +++++ .../gateway/context/GatewayConsulRepo.java | 82 ++++++++++++++----- .../core/constant/GatewayConstant.java | 16 ++++ .../core/plugin/OAuthGatewayPlugin.java | 15 +++- .../trace/TraceClientPreEnhancedPlugin.java | 2 +- .../TraceServerFinallyEnhancedPlugin.java | 74 +++++++++++++++++ .../trace/TraceServerPreEnhancedPlugin.java | 2 +- .../PolarisSpanAttributesProvider.java | 6 +- .../attribute/SpanAttributesProvider.java | 6 +- .../tsf/TsfSpanAttributesProvider.java | 53 ++++++++++++ .../TraceEnhancedPluginAutoConfiguration.java | 7 ++ .../context/PostInitPolarisSDKContext.java | 2 +- ...olarisContextEnvironmentPostProcessor.java | 2 +- .../tsf/TsfInstanceMetadataProvider.java | 2 +- .../RpcEnhancementAutoConfiguration.java | 61 ++++++++++++++ .../instrument/feign/EnhancedFeignClient.java | 11 ++- .../filter/EnhancedReactiveFilter.java | 10 ++- .../filter/EnhancedServletFilter.java | 3 +- ...lockingLoadBalancerClientInterceptor.java} | 15 +++- .../EnhancedRestTemplateInterceptor.java | 75 +++++++++++++++++ .../PolarisBlockingLoadBalancerClient.java | 8 +- ...PolarisLoadBalancerRequestTransformer.java | 6 ++ .../scg/EnhancedGatewayGlobalFilter.java | 4 +- ...hancedWebClientExchangeFilterFunction.java | 10 ++- .../plugin/EnhancedPluginType.java | 4 + .../plugin/PluginOrderConstant.java | 2 +- .../PolarisInstanceTransformer.java | 13 ++- .../enhancement/util/EnhancedPluginUtils.java | 54 ++++++++++++ 41 files changed, 638 insertions(+), 144 deletions(-) rename spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/{EncodeTransferMedataRestTemplateInterceptor.java => EncodeTransferMedataRestTemplateEnhancedPlugin.java} (79%) rename spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/{EncodeTransferMedataRestTemplateInterceptorTest.java => EnhancedRestTemplateInterceptorTest.java} (92%) create mode 100644 spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java create mode 100644 spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerFinallyEnhancedPlugin.java rename spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/{EnhancedRestTemplateWrapInterceptor.java => EnhancedRestTemplateBlockingLoadBalancerClientInterceptor.java} (87%) create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateInterceptor.java create mode 100644 spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/util/EnhancedPluginUtils.java diff --git a/.licenserc.yaml b/.licenserc.yaml index 6df7f7fc8..274bde341 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -16,7 +16,7 @@ header: CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. paths: - - "**/tencent/**" + - "**/*.java" language: Java: extensions: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e5564850..6c7a9b9ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,4 +5,5 @@ - [fix: fix ConfigChangeListener and unit test](https://github.com/Tencent/spring-cloud-tencent/pull/1654) - [feat: support spring-retry and feign config refresh and feign eager load support schema](https://github.com/Tencent/spring-cloud-tencent/pull/1649) - [fix: fix ConfigChangeListener ut bug](https://github.com/Tencent/spring-cloud-tencent/pull/1659) -- [feat: support tsf gw.](https://github.com/Tencent/spring-cloud-tencent/pull/1696) +- [feat: support tsf gw.](https://github.com/Tencent/spring-cloud-tencent/pull/1697) +- [fix: tsf related bugfixes](https://github.com/Tencent/spring-cloud-tencent/pull/1698) diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java index ddb077213..8df293f1c 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/config/MetadataTransferAutoConfiguration.java @@ -17,32 +17,20 @@ package com.tencent.cloud.metadata.config; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import com.tencent.cloud.common.constant.OrderConstant; import com.tencent.cloud.metadata.core.DecodeTransferMetadataReactiveFilter; import com.tencent.cloud.metadata.core.DecodeTransferMetadataServletFilter; import com.tencent.cloud.metadata.core.EncodeTransferMedataFeignEnhancedPlugin; -import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateInterceptor; +import com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin; import com.tencent.cloud.metadata.core.EncodeTransferMedataScgEnhancedPlugin; import com.tencent.cloud.metadata.core.EncodeTransferMedataWebClientEnhancedPlugin; -import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; -import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; -import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.util.CollectionUtils; -import org.springframework.web.client.RestTemplate; import static javax.servlet.DispatcherType.ASYNC; import static javax.servlet.DispatcherType.ERROR; @@ -130,59 +118,9 @@ public class MetadataTransferAutoConfiguration { @ConditionalOnProperty(value = "spring.cloud.tencent.rpc-enhancement.enabled", havingValue = "true", matchIfMissing = true) protected static class MetadataTransferRestTemplateConfig { - @Autowired(required = false) - private List restTemplates = Collections.emptyList(); - - @Bean - public EncodeTransferMedataRestTemplateInterceptor encodeTransferMedataRestTemplateInterceptor() { - return new EncodeTransferMedataRestTemplateInterceptor(); - } - - @Bean - public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTemplate(EncodeTransferMedataRestTemplateInterceptor interceptor) { - return () -> restTemplates.forEach(restTemplate -> { - List list = new ArrayList<>(restTemplate.getInterceptors()); - list.add(interceptor); - restTemplate.setInterceptors(list); - }); - } - @Bean - public RestTemplateCustomizer polarisRestTemplateCustomizer( - @Autowired(required = false) RetryLoadBalancerInterceptor retryLoadBalancerInterceptor, - @Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) { - return restTemplate -> { - List list = new ArrayList<>(restTemplate.getInterceptors()); - // LoadBalancerInterceptor must invoke before EncodeTransferMedataRestTemplateInterceptor - int addIndex = list.size(); - if (CollectionUtils.containsInstance(list, retryLoadBalancerInterceptor) || CollectionUtils.containsInstance(list, loadBalancerInterceptor)) { - ClientHttpRequestInterceptor enhancedRestTemplateInterceptor = null; - for (int i = 0; i < list.size(); i++) { - if (list.get(i) instanceof EncodeTransferMedataRestTemplateInterceptor) { - enhancedRestTemplateInterceptor = list.get(i); - addIndex = i; - } - } - if (enhancedRestTemplateInterceptor != null) { - list.remove(addIndex); - list.add(enhancedRestTemplateInterceptor); - } - } - else { - if (retryLoadBalancerInterceptor != null || loadBalancerInterceptor != null) { - for (int i = 0; i < list.size(); i++) { - if (list.get(i) instanceof EncodeTransferMedataRestTemplateInterceptor) { - addIndex = i; - } - } - list.add(addIndex, - retryLoadBalancerInterceptor != null - ? retryLoadBalancerInterceptor - : loadBalancerInterceptor); - } - } - restTemplate.setInterceptors(list); - }; + public EncodeTransferMedataRestTemplateEnhancedPlugin encodeTransferMedataRestTemplateEnhancedPlugin() { + return new EncodeTransferMedataRestTemplateEnhancedPlugin(); } } diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java similarity index 79% rename from spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java rename to spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java index 2c8e5af23..78d4ec463 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptor.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/main/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateEnhancedPlugin.java @@ -17,27 +17,23 @@ package com.tencent.cloud.metadata.core; -import java.io.IOException; import java.util.Map; -import com.tencent.cloud.common.constant.OrderConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.tsf.TsfContextUtils; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.common.util.TsfTagUtils; import com.tencent.cloud.common.util.UrlUtils; +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.PluginOrderConstant; import com.tencent.polaris.metadata.core.MessageMetadataContainer; import com.tencent.polaris.metadata.core.MetadataType; import shade.polaris.com.google.common.collect.ImmutableMap; -import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; -import org.springframework.core.Ordered; import org.springframework.http.HttpRequest; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.lang.NonNull; import org.springframework.util.CollectionUtils; import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.APPLICATION_METADATA; @@ -45,23 +41,23 @@ import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUST import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA; /** - * Interceptor used for adding the metadata in http headers from context when web client - * is RestTemplate. + * Pre EnhancedPlugin for rest template to encode transfer metadata. * - * It needs to execute after {@link LoadBalancerInterceptor}, because LaneRouter may add calleeTransitiveHeaders. - * - * @author Haotian Zhang + * @author Shedfree Wu */ -public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered { - +public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedPlugin { @Override - public int getOrder() { - return OrderConstant.Client.RestTemplate.ENCODE_TRANSFER_METADATA_INTERCEPTOR_ORDER; + public EnhancedPluginType getType() { + return EnhancedPluginType.Client.BEFORE_CALLING; } @Override - public ClientHttpResponse intercept(@NonNull HttpRequest httpRequest, @NonNull byte[] bytes, - @NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException { + public void run(EnhancedPluginContext context) throws Throwable { + if (!(context.getOriginRequest() instanceof HttpRequest)) { + return; + } + HttpRequest httpRequest = (HttpRequest) context.getOriginRequest(); + // get metadata of current thread MetadataContext metadataContext = MetadataContextHolder.get(); Map customMetadata = metadataContext.getCustomMetadata(); @@ -91,8 +87,6 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe } // set headers that need to be transmitted from the upstream this.buildTransmittedHeader(httpRequest, transHeaders); - - return clientHttpRequestExecution.execute(httpRequest, bytes); } private void buildTransmittedHeader(HttpRequest request, Map transHeaders) { @@ -121,4 +115,9 @@ public class EncodeTransferMedataRestTemplateInterceptor implements ClientHttpRe buildHeaderMap(request, ImmutableMap.of(headerName, JacksonUtils.serialize2Json(metadata))); } } + + @Override + public int getOrder() { + return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER; + } } diff --git a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EnhancedRestTemplateInterceptorTest.java similarity index 92% rename from spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java rename to spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EnhancedRestTemplateInterceptorTest.java index ef4a7ac4e..a7bc17d35 100644 --- a/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EncodeTransferMedataRestTemplateInterceptorTest.java +++ b/spring-cloud-starter-tencent-metadata-transfer/src/test/java/com/tencent/cloud/metadata/core/EnhancedRestTemplateInterceptorTest.java @@ -22,6 +22,7 @@ import java.util.Map; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateInterceptor; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -43,16 +44,16 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; /** - * Test for {@link EncodeTransferMedataRestTemplateInterceptor}. + * Test for {@link EnhancedRestTemplateInterceptor}. * * @author Haotian Zhang */ @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = RANDOM_PORT, - classes = EncodeTransferMedataRestTemplateInterceptorTest.TestApplication.class, + classes = EnhancedRestTemplateInterceptorTest.TestApplication.class, properties = {"spring.config.location = classpath:application-test.yml", "spring.main.web-application-type = reactive"}) -public class EncodeTransferMedataRestTemplateInterceptorTest { +public class EnhancedRestTemplateInterceptorTest { @Autowired private RestTemplate restTemplate; diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/extend/consul/ConsulDiscoveryUtil.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/extend/consul/ConsulDiscoveryUtil.java index 3bfba0fa4..9a29e6481 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/extend/consul/ConsulDiscoveryUtil.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/extend/consul/ConsulDiscoveryUtil.java @@ -65,7 +65,7 @@ public final class ConsulDiscoveryUtil { if (StringUtils.isNotBlank(appName)) { return appName; } - return env.getProperty("spring.application.name", "application"); + return env.getProperty("spring.application.name"); } public static String getInstanceId(ConsulDiscoveryProperties properties, ApplicationContext context) { diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java index a5ed8373f..952b7c3be 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/registry/PolarisServiceRegistry.java @@ -25,6 +25,7 @@ import java.util.concurrent.ScheduledExecutorService; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.StaticMetadataManager; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; import com.tencent.cloud.common.util.OkHttpUtil; import com.tencent.cloud.common.util.OtUtils; import com.tencent.cloud.polaris.PolarisDiscoveryProperties; @@ -101,13 +102,18 @@ public class PolarisServiceRegistry implements ServiceRegistry getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller) { MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller); Map values = new HashMap<>(); diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java new file mode 100644 index 000000000..ea889bc38 --- /dev/null +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/MetadataContextUtils.java @@ -0,0 +1,49 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 Tencent. 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.common.util; + +import java.util.Optional; + +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.polaris.metadata.core.MetadataObjectValue; +import com.tencent.polaris.metadata.core.MetadataType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utils for MetadataContext. + * + * @author Shedfree Wu + */ +public final class MetadataContextUtils { + + private static final Logger LOG = LoggerFactory.getLogger(MetadataContextUtils.class); + + private MetadataContextUtils() { + } + + public static void putMetadataObjectValue(String key, Object value) { + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(key, value); + } + + public static boolean existMetadataValue(MetadataObjectValue metadataObjectValue) { + return Optional.ofNullable(metadataObjectValue).map(MetadataObjectValue::getObjectValue). + map(Optional::isPresent).orElse(false); + } +} diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/TsfTagUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/TsfTagUtils.java index fb89182cf..c3f9a5786 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/TsfTagUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/TsfTagUtils.java @@ -27,6 +27,7 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import com.tencent.cloud.common.constant.ContextConstant; import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.tsf.TsfContextUtils; import com.tencent.polaris.api.utils.CollectionUtils; @@ -114,6 +115,7 @@ public final class TsfTagUtils { if (laneTag != null) { tsfSystemTags.add(laneTag); + MetadataContextUtils.putMetadataObjectValue(ContextConstant.LANE_TAG, laneTag); } if (CollectionUtils.isNotEmpty(tsfUserTags)) { diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java index 66eb9caf9..4f0c6e675 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java @@ -28,9 +28,11 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import com.tencent.cloud.common.constant.ContextConstant; import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.common.util.MetadataContextUtils; import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.StringUtils; import com.tencent.tsf.gateway.core.TsfGatewayRequest; @@ -240,6 +242,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { throw NotFoundException.create(true, msg); } updateRouteMetadata(exchange, contextRoute); + setTraceAttributes(contextRoute, GatewayConstant.NON_UNIT_TYPE, GatewayConstant.NON_UNIT_TRANSFER_TYPE); exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute); URI requestUri = URI.create(contextRoute.getHost() + apis[1]); @@ -261,6 +264,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { throw NotFoundException.create(true, msg); } updateRouteMetadata(exchange, contextRoute); + setTraceAttributes(contextRoute, GatewayConstant.NON_UNIT_TYPE, GatewayConstant.NON_UNIT_TRANSFER_TYPE); exchange.getAttributes().put(GatewayConstant.CONTEXT_ROUTE, contextRoute); MetadataContext metadataContext = exchange.getAttribute( @@ -494,4 +498,22 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { throw new IllegalStateException("Invalid URI query: \"" + query + "\""); } } + + private void setTraceAttributes(GroupContext.ContextRoute contextRoute, String unitType, String unitTransferType) { + + Map traceAttributes = new HashMap<>(); + traceAttributes.put("tsf-ms-type", "MSGW"); + traceAttributes.put("tsf-unit-type", unitType); + traceAttributes.put("tsf-unit-transfer-type", unitTransferType); + traceAttributes.put("destination.namespace-id", contextRoute.getNamespaceId()); + traceAttributes.put("tsf-msgw-group", config.getGroup()); + traceAttributes.put("tsf-msgw-groupApi", contextRoute.getApiId()); + traceAttributes.put("tsf-msgw-apiPath", contextRoute.getPath()); + traceAttributes.put("tsf-msgw-apiMethod", contextRoute.getMethod()); + traceAttributes.put("tsf-msgw-namespaceName", contextRoute.getNamespace()); + traceAttributes.put("tsf-msgw-serviceName", contextRoute.getService()); + traceAttributes.put("localComponent", "msgw"); + + MetadataContextUtils.putMetadataObjectValue(ContextConstant.Trace.EXTRA_TRACE_ATTRIBUTES, traceAttributes); + } } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/GatewayConsulRepo.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/GatewayConsulRepo.java index 4e4da3cef..4cd07f1e6 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/GatewayConsulRepo.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/GatewayConsulRepo.java @@ -18,8 +18,10 @@ package com.tencent.cloud.plugin.gateway.context; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URI; import java.util.ArrayList; @@ -63,6 +65,7 @@ import com.tencent.tsf.gateway.core.model.PathWildcardRule; import com.tencent.tsf.gateway.core.model.PluginInstanceInfoResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import shade.polaris.org.apache.commons.io.IOUtils; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.filter.FilterDefinition; @@ -126,6 +129,10 @@ public class GatewayConsulRepo { if (listResponse.getValue() != null) { refreshGatewayGroupConfig(parseGroupResponse(listResponse)); } + else { + logger.info("try to load gateway group config from local file."); + refreshGatewayGroupConfig(loadResponseFromFile()); + } scheduledExecutorService.scheduleAtFixedRate(() -> { try { @@ -257,6 +264,35 @@ public class GatewayConsulRepo { } + private GatewayAllResult loadResponseFromFile() { + GroupResult groupResult = (GroupResult) readLocalRepo(GatewayConstant.GROUP_FILE_NAME, GroupResult.class); + GroupApiResult groupApiResult = (GroupApiResult) readLocalRepo(GatewayConstant.API_FILE_NAME, GroupApiResult.class); + PathRewriteResult pathRewriteResult = (PathRewriteResult) readLocalRepo(GatewayConstant.PATH_REWRITE_FILE_NAME, PathRewriteResult.class); + PathWildcardResult pathWildcardResult = (PathWildcardResult) readLocalRepo(GatewayConstant.PATH_WILDCARD_FILE_NAME, PathWildcardResult.class); + return new GatewayAllResult(groupResult, groupApiResult, pathRewriteResult, pathWildcardResult); + } + + private Object readLocalRepo(String type, Class repoResultClazz) { + byte[] bytes; + try (FileInputStream fin = new FileInputStream(getRepoStoreFile(type)); InputStreamReader isr = new InputStreamReader(fin)) { + bytes = IOUtils.toByteArray(isr, "utf-8"); + if (bytes == null || bytes.length == 0) { + return null; + } + } + catch (IOException t) { + logger.warn("[readLocalRepo] read group info from file occur exception: {}", t.getMessage()); + return null; + } + try { + return JacksonUtils.deserialize(new String(bytes, "utf-8"), repoResultClazz); + } + catch (Throwable t) { + logger.warn("[readLocalRepo] json serialize data to group occur exception: {}", t.getMessage()); + return null; + } + } + private GatewayAllResult parseGroupResponse(Response> listResponse) { GroupResult groupResult = null; GroupApiResult groupApiResult = new GroupApiResult(); @@ -362,30 +398,32 @@ public class GatewayConsulRepo { } } - for (GroupApi groupApi : groupApiResult.getResult()) { - GroupContext groupContext = groups.get(groupApi.getGroupId()); - if (groupContext == null) { - if (logger.isDebugEnabled()) { - logger.debug("group api {} not found in group {}", groupApi.getApiId(), groupApi.getGroupId()); + if (groupApiResult != null) { + for (GroupApi groupApi : groupApiResult.getResult()) { + GroupContext groupContext = groups.get(groupApi.getGroupId()); + if (groupContext == null) { + if (logger.isDebugEnabled()) { + logger.debug("group api {} not found in group {}", groupApi.getApiId(), groupApi.getGroupId()); + } + continue; } - continue; - } - GroupContext.ContextRoute contextRoute = new GroupContext.ContextRoute(); - contextRoute.setApiId(groupApi.getApiId()); - contextRoute.setHost(groupApi.getHost()); - contextRoute.setPath(groupApi.getPath()); - contextRoute.setPathMapping(groupApi.getPathMapping()); - contextRoute.setMethod(groupApi.getMethod()); - contextRoute.setService(groupApi.getServiceName()); - contextRoute.setNamespaceId(groupApi.getNamespaceId()); - contextRoute.setNamespace(groupApi.getNamespaceName()); - if (groupApi.getTimeout() != null) { - Map metadata = new HashMap<>(); - metadata.put("response-timeout", String.valueOf(groupApi.getTimeout())); - contextRoute.setMetadata(metadata); + GroupContext.ContextRoute contextRoute = new GroupContext.ContextRoute(); + contextRoute.setApiId(groupApi.getApiId()); + contextRoute.setHost(groupApi.getHost()); + contextRoute.setPath(groupApi.getPath()); + contextRoute.setPathMapping(groupApi.getPathMapping()); + contextRoute.setMethod(groupApi.getMethod()); + contextRoute.setService(groupApi.getServiceName()); + contextRoute.setNamespaceId(groupApi.getNamespaceId()); + contextRoute.setNamespace(groupApi.getNamespaceName()); + if (groupApi.getTimeout() != null) { + Map metadata = new HashMap<>(); + metadata.put("response-timeout", String.valueOf(groupApi.getTimeout())); + contextRoute.setMetadata(metadata); + } + groupContext.getRoutes().add(contextRoute); } - groupContext.getRoutes().add(contextRoute); } if (pathWildcardResult != null && pathWildcardResult.getResult() != null) { @@ -410,7 +448,7 @@ public class GatewayConsulRepo { contextGatewayProperties.setGroups(groups); contextGatewayProperties.setRoutes(routes); - contextGatewayProperties.setPathRewrites(Optional.ofNullable(pathRewriteResult.getResult()) + contextGatewayProperties.setPathRewrites(Optional.ofNullable(pathRewriteResult).map(PathRewriteResult::getResult) .orElse(new ArrayList<>())); logger.debug("Gateway config loaded. :{}", JacksonUtils.serialize2Json(contextGatewayProperties)); diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/constant/GatewayConstant.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/constant/GatewayConstant.java index d22e7f633..adcce6616 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/constant/GatewayConstant.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/constant/GatewayConstant.java @@ -74,6 +74,22 @@ public final class GatewayConstant { * Gateway 本地仓库的文件目录. */ public static final String GATEWAY_REPO_PREFIX = GATEWAY_REPO_ROOT + "/tsf/gateway/"; + /** + * NON_UNIT_TYPE. + */ + public static final String NON_UNIT_TYPE = "non-unit"; + /** + * NON_UNIT_TRANSFER_TYPE. + */ + public static final String NON_UNIT_TRANSFER_TYPE = "non-unit"; + /** + * UNIT_TYPE. + */ + public static final String UNIT_TYPE = "unit"; + /** + * UNIT_TRANSFER_TYPE. + */ + public static final String UNIT_TRANSFER_TYPE = "ms_unit_proxy"; private GatewayConstant() { diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/plugin/OAuthGatewayPlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/plugin/OAuthGatewayPlugin.java index 14b2694cb..ea16b841c 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/plugin/OAuthGatewayPlugin.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/tsf/gateway/core/plugin/OAuthGatewayPlugin.java @@ -28,6 +28,7 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.plugin.gateway.context.Position; import com.tencent.cloud.polaris.context.PolarisSDKContextManager; +import com.tencent.polaris.api.utils.ClassUtils; import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.assembly.api.AssemblyAPI; import com.tencent.polaris.assembly.api.pojo.TraceAttributes; @@ -39,6 +40,7 @@ import com.tencent.tsf.gateway.core.http.HttpConnectionPoolUtil; import com.tencent.tsf.gateway.core.model.OAuthPlugin; import com.tencent.tsf.gateway.core.model.OAuthResult; import com.tencent.tsf.gateway.core.model.PluginPayload; +import io.opentelemetry.context.Scope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -196,7 +198,7 @@ public class OAuthGatewayPlugin implements IGatewayPlugin { throw new TsfGatewayException(TsfGatewayError.GATEWAY_REQUEST_NOT_FOUND, "Unable to find instance for " + pluginInfo.getTokenAuthServiceName()); } - fillTracingContext(namespace, serviceName); + Object otScope = fillTracingContext(namespace, serviceName); String newRequestUrl = uri.getScheme() + "://" + GATEWAY_WILDCARD_SERVICE_NAME + tokenAuthUrl; URI newUri = new URI(newRequestUrl); @@ -204,7 +206,12 @@ public class OAuthGatewayPlugin implements IGatewayPlugin { // http://127.0.0.1:8080/group1/namespace1/Consumer-demo/echo-rest/1?user=1 URI requestUrl = this.reconstructURI(new OauthDelegatingServiceInstance(instance.getServer()), newUri); logger.debug("LoadBalancerClientFilter url chosen: " + requestUrl); - return sendAuthRequestByHttpMethod(paramsMap, headerParamsMap, requestUrl.toASCIIString(), tokenAuthMethod, timeout); + String result = sendAuthRequestByHttpMethod(paramsMap, headerParamsMap, requestUrl.toASCIIString(), tokenAuthMethod, timeout); + + if (ClassUtils.isClassPresent("io.opentelemetry.context.Scope") && otScope instanceof Scope) { + ((Scope) otScope).close(); + } + return result; } catch (Exception e) { logger.error("MicroService {} Request Auth Server Error", tokenAuthMethod, e); @@ -244,7 +251,7 @@ public class OAuthGatewayPlugin implements IGatewayPlugin { } } - void fillTracingContext(String namespace, String serviceName) { + Object fillTracingContext(String namespace, String serviceName) { Map attributes = new HashMap<>(); attributes.put("net.peer.service", serviceName); @@ -256,6 +263,8 @@ public class OAuthGatewayPlugin implements IGatewayPlugin { AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI(); assemblyAPI.updateTraceAttributes(traceAttributes); + + return traceAttributes.getOtScope(); } class OauthDelegatingServiceInstance implements ServiceInstance { diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientPreEnhancedPlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientPreEnhancedPlugin.java index f3b22602b..52cc7e348 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientPreEnhancedPlugin.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientPreEnhancedPlugin.java @@ -44,7 +44,7 @@ public class TraceClientPreEnhancedPlugin implements EnhancedPlugin { @Override public EnhancedPluginType getType() { - return EnhancedPluginType.Client.PRE; + return EnhancedPluginType.Client.BEFORE_CALLING; } @Override diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerFinallyEnhancedPlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerFinallyEnhancedPlugin.java new file mode 100644 index 000000000..f9d00a3ed --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerFinallyEnhancedPlugin.java @@ -0,0 +1,74 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 Tencent. 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.plugin.trace; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider; +import com.tencent.cloud.polaris.context.PolarisSDKContextManager; +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.PluginOrderConstant; +import com.tencent.polaris.api.utils.CollectionUtils; +import com.tencent.polaris.assembly.api.AssemblyAPI; +import com.tencent.polaris.assembly.api.pojo.TraceAttributes; + +public class TraceServerFinallyEnhancedPlugin implements EnhancedPlugin { + + private final PolarisSDKContextManager polarisSDKContextManager; + + private final List spanAttributesProviderList; + + public TraceServerFinallyEnhancedPlugin(PolarisSDKContextManager polarisSDKContextManager, List spanAttributesProviderList) { + this.polarisSDKContextManager = polarisSDKContextManager; + this.spanAttributesProviderList = spanAttributesProviderList; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Server.FINALLY; + } + + @Override + public void run(EnhancedPluginContext context) throws Throwable { + Map attributes = new HashMap<>(); + if (CollectionUtils.isNotEmpty(spanAttributesProviderList)) { + for (SpanAttributesProvider spanAttributesProvider : spanAttributesProviderList) { + Map additionalAttributes = spanAttributesProvider.getServerFinallySpanAttributes(context); + if (CollectionUtils.isNotEmpty(additionalAttributes)) { + attributes.putAll(additionalAttributes); + } + } + } + + TraceAttributes traceAttributes = new TraceAttributes(); + traceAttributes.setAttributes(attributes); + traceAttributes.setAttributeLocation(TraceAttributes.AttributeLocation.SPAN); + + AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI(); + assemblyAPI.updateTraceAttributes(traceAttributes); + } + + @Override + public int getOrder() { + return PluginOrderConstant.ServerPluginOrder.TRACE_SERVER_PRE_PLUGIN_ORDER; + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerPreEnhancedPlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerPreEnhancedPlugin.java index 529f818f8..5d6e28269 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerPreEnhancedPlugin.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerPreEnhancedPlugin.java @@ -52,7 +52,7 @@ public class TraceServerPreEnhancedPlugin implements EnhancedPlugin { Map attributes = new HashMap<>(); if (CollectionUtils.isNotEmpty(spanAttributesProviderList)) { for (SpanAttributesProvider spanAttributesProvider : spanAttributesProviderList) { - Map additionalAttributes = spanAttributesProvider.getServerSpanAttributes(context); + Map additionalAttributes = spanAttributesProvider.getServerPreSpanAttributes(context); if (CollectionUtils.isNotEmpty(additionalAttributes)) { attributes.putAll(additionalAttributes); } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/PolarisSpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/PolarisSpanAttributesProvider.java index 94c767625..4be2eec96 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/PolarisSpanAttributesProvider.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/PolarisSpanAttributesProvider.java @@ -20,6 +20,7 @@ package com.tencent.cloud.plugin.trace.attribute; import java.util.HashMap; import java.util.Map; +import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; @@ -40,7 +41,7 @@ import static com.tencent.polaris.plugins.router.lane.LaneRouter.TRAFFIC_STAIN_L */ public class PolarisSpanAttributesProvider implements SpanAttributesProvider { @Override - public Map getServerSpanAttributes(EnhancedPluginContext context) { + public Map getServerPreSpanAttributes(EnhancedPluginContext context) { Map attributes = new HashMap<>(); MetadataContext metadataContext = MetadataContextHolder.get(); Map transitiveCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); @@ -59,6 +60,9 @@ public class PolarisSpanAttributesProvider implements SpanAttributesProvider { if (CollectionUtils.isNotEmpty(upstreamDisposableCustomAttributes)) { for (Map.Entry entry : upstreamDisposableCustomAttributes.entrySet()) { attributes.put("custom." + entry.getKey(), entry.getValue()); + if (MetadataConstant.DefaultMetadata.DEFAULT_METADATA_SOURCE_SERVICE_NAME.equals(entry.getKey())) { + attributes.put("net.peer.service", entry.getValue()); + } } } attributes.put("http.port", CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer() diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/SpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/SpanAttributesProvider.java index 5a09a8d2c..ab4c97b85 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/SpanAttributesProvider.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/SpanAttributesProvider.java @@ -29,7 +29,11 @@ public interface SpanAttributesProvider { */ String OT_SCOPE_KEY = "OT_SCOPE_KEY"; - default Map getServerSpanAttributes(EnhancedPluginContext context) { + default Map getServerPreSpanAttributes(EnhancedPluginContext context) { + return new HashMap<>(); + } + + default Map getServerFinallySpanAttributes(EnhancedPluginContext context) { return new HashMap<>(); } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java index 0cb610ff5..3913b8173 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/attribute/tsf/TsfSpanAttributesProvider.java @@ -20,13 +20,22 @@ package com.tencent.cloud.plugin.trace.attribute.tsf; import java.util.HashMap; import java.util.Map; +import com.tencent.cloud.common.constant.ContextConstant; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.common.util.MetadataContextUtils; +import com.tencent.cloud.common.util.OtUtils; import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.StringUtils; +import com.tencent.polaris.metadata.core.MetadataObjectValue; +import com.tencent.polaris.metadata.core.MetadataType; import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants; +import com.tencent.polaris.plugins.router.lane.LaneRouter; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.tsf.core.entity.Tag; public class TsfSpanAttributesProvider implements SpanAttributesProvider { @@ -54,6 +63,50 @@ public class TsfSpanAttributesProvider implements SpanAttributesProvider { if (StringUtils.isBlank(attributes.get("remote.namespace-id"))) { attributes.put("remote.namespace-id", context.getRequest().getGovernanceNamespace()); } + + MetadataObjectValue langTagObject = MetadataContextHolder.get(). + getMetadataContainer(MetadataType.APPLICATION, true). + getMetadataValue(ContextConstant.LANE_TAG); + if (MetadataContextUtils.existMetadataValue(langTagObject)) { + attributes.put(OtUtils.OTEL_LANE_ID_KEY, langTagObject.getObjectValue().get().getValue()); + } + + MetadataObjectValue> extraTraceAttributeObject = MetadataContextHolder.get(). + getMetadataContainer(MetadataType.APPLICATION, true). + getMetadataValue(ContextConstant.Trace.EXTRA_TRACE_ATTRIBUTES); + if (MetadataContextUtils.existMetadataValue(extraTraceAttributeObject)) { + Map extraTraceAttributes = extraTraceAttributeObject.getObjectValue().get(); + attributes.putAll(extraTraceAttributes); + } + return attributes; + } + + @Override + public Map getServerPreSpanAttributes(EnhancedPluginContext context) { + Map attributes = new HashMap<>(); + + MetadataContext metadataContext = MetadataContextHolder.get(); + Map upstreamDisposableCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_UPSTREAM_DISPOSABLE); + if (CollectionUtils.isNotEmpty(upstreamDisposableCustomAttributes)) { + for (Map.Entry entry : upstreamDisposableCustomAttributes.entrySet()) { + if (LaneRouter.TRAFFIC_STAIN_LABEL.equals(entry.getKey()) && entry.getValue().startsWith("tsf/")) { + attributes.put(OtUtils.OTEL_LANE_ID_KEY, entry.getValue().split("/")[1]); + } + } + } + return attributes; + } + + @Override + public Map getServerFinallySpanAttributes(EnhancedPluginContext context) { + Map attributes = new HashMap<>(); + MetadataObjectValue> extraTraceAttributeObject = MetadataContextHolder.get(). + getMetadataContainer(MetadataType.APPLICATION, true). + getMetadataValue(ContextConstant.Trace.EXTRA_TRACE_ATTRIBUTES); + if (MetadataContextUtils.existMetadataValue(extraTraceAttributeObject)) { + Map extraTraceAttributes = extraTraceAttributeObject.getObjectValue().get(); + attributes.putAll(extraTraceAttributes); + } return attributes; } } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceEnhancedPluginAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceEnhancedPluginAutoConfiguration.java index b9b5c351d..7991205fd 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceEnhancedPluginAutoConfiguration.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceEnhancedPluginAutoConfiguration.java @@ -21,6 +21,7 @@ import java.util.List; import com.tencent.cloud.plugin.trace.TraceClientFinallyEnhancedPlugin; import com.tencent.cloud.plugin.trace.TraceClientPreEnhancedPlugin; +import com.tencent.cloud.plugin.trace.TraceServerFinallyEnhancedPlugin; import com.tencent.cloud.plugin.trace.TraceServerPreEnhancedPlugin; import com.tencent.cloud.plugin.trace.attribute.PolarisSpanAttributesProvider; import com.tencent.cloud.plugin.trace.attribute.SpanAttributesProvider; @@ -46,6 +47,12 @@ public class TraceEnhancedPluginAutoConfiguration { return new TraceServerPreEnhancedPlugin(polarisSDKContextManager, spanAttributesProviderList); } + @Bean + public TraceServerFinallyEnhancedPlugin traceServerFinallyEnhancedPlugin( + PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) List spanAttributesProviderList) { + return new TraceServerFinallyEnhancedPlugin(polarisSDKContextManager, spanAttributesProviderList); + } + @Bean public TraceClientPreEnhancedPlugin traceClientPreEnhancedPlugin( PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) List spanAttributesProviderList) { diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PostInitPolarisSDKContext.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PostInitPolarisSDKContext.java index fadb83d84..115bce3d3 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PostInitPolarisSDKContext.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/PostInitPolarisSDKContext.java @@ -40,7 +40,7 @@ public class PostInitPolarisSDKContext { if (StringUtils.isNotBlank(region)) { valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.REGION.name(), region); } - if (StringUtils.isNotBlank(zone)) { + if (zone != null) { valueContext.setValue(RoutingProto.NearbyRoutingConfig.LocationLevel.ZONE.name(), zone); } if (StringUtils.isNotBlank(campus)) { diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextEnvironmentPostProcessor.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextEnvironmentPostProcessor.java index 9078ec4a5..74eef69b5 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextEnvironmentPostProcessor.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/PolarisContextEnvironmentPostProcessor.java @@ -96,7 +96,7 @@ public final class PolarisContextEnvironmentPostProcessor implements Environment // zone String zone = environment.getProperty("tsf_zone"); - if (StringUtils.isNotBlank(zone)) { + if (zone != null) { polarisEnvProperties.put("spring.cloud.tencent.metadata.content.zone", zone); } diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfInstanceMetadataProvider.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfInstanceMetadataProvider.java index f46335472..60b8d9221 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfInstanceMetadataProvider.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/config/extend/tsf/TsfInstanceMetadataProvider.java @@ -68,7 +68,7 @@ public class TsfInstanceMetadataProvider implements InstanceMetadataProvider { tsfMetadata.put(TsfMetadataConstants.TSF_REGION, tsfCoreProperties.getTsfRegion()); } - if (StringUtils.isNotBlank(tsfCoreProperties.getTsfZone())) { + if (tsfCoreProperties.getTsfZone() != null) { tsfMetadata.put(TsfMetadataConstants.TSF_ZONE, tsfCoreProperties.getTsfZone()); } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java index 06e8dd5a2..4dc39d0ad 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java @@ -17,6 +17,7 @@ package com.tencent.cloud.rpc.enhancement.config; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -28,6 +29,7 @@ import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedFeignBeanPostP import com.tencent.cloud.rpc.enhancement.instrument.feign.EnhancedLoadBalancerClientAspect; import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedReactiveFilter; import com.tencent.cloud.rpc.enhancement.instrument.filter.EnhancedServletFilter; +import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.EnhancedRestTemplateInterceptor; import com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer; import com.tencent.cloud.rpc.enhancement.instrument.scg.EnhancedGatewayGlobalFilter; import com.tencent.cloud.rpc.enhancement.instrument.webclient.EnhancedWebClientExchangeFilterFunction; @@ -53,12 +55,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; +import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; +import org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Role; import org.springframework.core.annotation.Order; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; @@ -182,6 +189,9 @@ public class RpcEnhancementAutoConfiguration { @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") protected static class PolarisRestTemplateAutoConfiguration { + @Autowired(required = false) + private List restTemplates = Collections.emptyList(); + @Bean @ConditionalOnMissingBean @ConditionalOnClass(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer"}) @@ -195,6 +205,57 @@ public class RpcEnhancementAutoConfiguration { return new BlockingLoadBalancerClientBeanPostProcessor(); } + @Bean + public EnhancedRestTemplateInterceptor enhancedRestTemplateInterceptor(EnhancedPluginRunner pluginRunner) { + return new EnhancedRestTemplateInterceptor(pluginRunner); + } + + @Bean + public SmartInitializingSingleton addEncodeTransferMetadataInterceptorForRestTemplate(EnhancedRestTemplateInterceptor interceptor) { + return () -> restTemplates.forEach(restTemplate -> { + List list = new ArrayList<>(restTemplate.getInterceptors()); + list.add(interceptor); + restTemplate.setInterceptors(list); + }); + } + + @Bean + public RestTemplateCustomizer polarisRestTemplateCustomizer( + @Autowired(required = false) RetryLoadBalancerInterceptor retryLoadBalancerInterceptor, + @Autowired(required = false) LoadBalancerInterceptor loadBalancerInterceptor) { + return restTemplate -> { + List list = new ArrayList<>(restTemplate.getInterceptors()); + // LoadBalancerInterceptor must invoke before EncodeTransferMedataRestTemplateInterceptor + int addIndex = list.size(); + if (CollectionUtils.containsInstance(list, retryLoadBalancerInterceptor) || CollectionUtils.containsInstance(list, loadBalancerInterceptor)) { + ClientHttpRequestInterceptor enhancedRestTemplateInterceptor = null; + for (int i = 0; i < list.size(); i++) { + if (list.get(i) instanceof EnhancedRestTemplateInterceptor) { + enhancedRestTemplateInterceptor = list.get(i); + addIndex = i; + } + } + if (enhancedRestTemplateInterceptor != null) { + list.remove(addIndex); + list.add(enhancedRestTemplateInterceptor); + } + } + else { + if (retryLoadBalancerInterceptor != null || loadBalancerInterceptor != null) { + for (int i = 0; i < list.size(); i++) { + if (list.get(i) instanceof EnhancedRestTemplateInterceptor) { + addIndex = i; + } + } + list.add(addIndex, + retryLoadBalancerInterceptor != null + ? retryLoadBalancerInterceptor + : loadBalancerInterceptor); + } + } + restTemplate.setInterceptors(list); + }; + } } /** diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignClient.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignClient.java index 0e9553660..c4018100a 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignClient.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/feign/EnhancedFeignClient.java @@ -26,11 +26,15 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import com.tencent.cloud.common.constant.MetadataConstant; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import com.tencent.polaris.api.pojo.CircuitBreakerStatus; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import feign.Client; @@ -63,7 +67,7 @@ public class EnhancedFeignClient implements Client { @Override public Response execute(Request request, Options options) throws IOException { - EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext(); HttpHeaders requestHeaders = new HttpHeaders(); request.headers().forEach((s, strings) -> requestHeaders.addAll(s, new ArrayList<>(strings))); @@ -71,11 +75,15 @@ public class EnhancedFeignClient implements Client { URI serviceUrl = url.resolve(request.requestTemplate().url()); + String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE, + MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE); + EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() .httpHeaders(requestHeaders) .httpMethod(HttpMethod.valueOf(request.httpMethod().name())) .url(url) .serviceUrl(serviceUrl) + .governanceNamespace(governanceNamespace) .build(); enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setOriginRequest(request); @@ -97,6 +105,7 @@ public class EnhancedFeignClient implements Client { try { // Run pre enhanced plugins. pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext); startMillis = System.currentTimeMillis(); Response response = delegate.execute(request, options); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedReactiveFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedReactiveFilter.java index be1fe8073..e624221c6 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedReactiveFilter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedReactiveFilter.java @@ -17,12 +17,16 @@ package com.tencent.cloud.rpc.enhancement.instrument.filter; +import com.tencent.cloud.common.constant.MetadataConstant; import com.tencent.cloud.common.constant.OrderConstant; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import reactor.core.publisher.Mono; import org.springframework.core.Ordered; @@ -45,7 +49,7 @@ public class EnhancedReactiveFilter implements WebFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext(); EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() .httpHeaders(exchange.getRequest().getHeaders()) @@ -80,6 +84,10 @@ public class EnhancedReactiveFilter implements WebFilter, Ordered { pluginRunner.run(EnhancedPluginType.Server.EXCEPTION, enhancedPluginContext); }) .doFinally(v -> { + if (exchange.getAttributes().containsKey(MetadataConstant.HeaderName.METADATA_CONTEXT)) { + MetadataContextHolder.set((MetadataContext) exchange.getAttributes().get( + MetadataConstant.HeaderName.METADATA_CONTEXT)); + } // Run finally enhanced plugins. pluginRunner.run(EnhancedPluginType.Server.FINALLY, enhancedPluginContext); }); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedServletFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedServletFilter.java index 43ef1ea9a..6119b5efd 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedServletFilter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/filter/EnhancedServletFilter.java @@ -35,6 +35,7 @@ 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 com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import org.springframework.core.annotation.Order; import org.springframework.http.HttpHeaders; @@ -57,7 +58,7 @@ public class EnhancedServletFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext(); HttpHeaders requestHeaders = new HttpHeaders(); Enumeration requestHeaderNames = request.getHeaderNames(); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateWrapInterceptor.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateBlockingLoadBalancerClientInterceptor.java similarity index 87% rename from spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateWrapInterceptor.java rename to spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateBlockingLoadBalancerClientInterceptor.java index cb29597f3..4aa74c050 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateWrapInterceptor.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateBlockingLoadBalancerClientInterceptor.java @@ -22,12 +22,15 @@ import java.net.URI; import java.util.Optional; import com.tencent.cloud.common.constant.ContextConstant; +import com.tencent.cloud.common.constant.MetadataConstant; +import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import com.tencent.polaris.metadata.core.MetadataObjectValue; import com.tencent.polaris.metadata.core.MetadataType; @@ -42,17 +45,17 @@ import org.springframework.http.client.ClientHttpResponse; import static com.tencent.cloud.rpc.enhancement.instrument.resttemplate.PolarisLoadBalancerRequestTransformer.LOAD_BALANCER_SERVICE_INSTANCE; /** - * EnhancedRestTemplateInterceptor. + * Interceptor used for pre-plugin, post-plugin, exception-plugin, and final-plugin in RestTemplate. * * @author sean yu */ -public class EnhancedRestTemplateWrapInterceptor { +public class EnhancedRestTemplateBlockingLoadBalancerClientInterceptor { private final EnhancedPluginRunner pluginRunner; private final LoadBalancerClient delegate; - public EnhancedRestTemplateWrapInterceptor(EnhancedPluginRunner pluginRunner, LoadBalancerClient delegate) { + public EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(EnhancedPluginRunner pluginRunner, LoadBalancerClient delegate) { this.pluginRunner = pluginRunner; this.delegate = delegate; } @@ -61,18 +64,22 @@ public class EnhancedRestTemplateWrapInterceptor { public T intercept(HttpRequest httpRequest, String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest loadBalancerRequest) throws IOException { - EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext(); URI serviceUrl = httpRequest.getURI(); if (httpRequest instanceof ServiceRequestWrapper) { serviceUrl = ((ServiceRequestWrapper) httpRequest).getRequest().getURI(); } + String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE, + MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE); + EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() .httpHeaders(httpRequest.getHeaders()) .httpMethod(httpRequest.getMethod()) .url(httpRequest.getURI()) .serviceUrl(serviceUrl) + .governanceNamespace(governanceNamespace) .build(); enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setOriginRequest(httpRequest); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateInterceptor.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateInterceptor.java new file mode 100644 index 000000000..a04cfbf5d --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/EnhancedRestTemplateInterceptor.java @@ -0,0 +1,75 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 Tencent. 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.instrument.resttemplate; + +import java.io.IOException; + +import com.tencent.cloud.common.constant.OrderConstant; +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.util.EnhancedPluginUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; +import org.springframework.core.Ordered; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.lang.NonNull; + +/** + * Interceptor used for before calling plugin in RestTemplate. + * + * It needs to execute after {@link LoadBalancerInterceptor}, because LaneRouter may add calleeTransitiveHeaders. + * + * @author Haotian Zhang + */ +public class EnhancedRestTemplateInterceptor implements ClientHttpRequestInterceptor, Ordered { + + private static final Logger LOG = LoggerFactory.getLogger(EnhancedRestTemplateInterceptor.class); + + private final EnhancedPluginRunner pluginRunner; + + public EnhancedRestTemplateInterceptor(EnhancedPluginRunner pluginRunner) { + this.pluginRunner = pluginRunner; + } + + @Override + public int getOrder() { + return OrderConstant.Client.RestTemplate.ENHANCE_INTERCEPTOR_ORDER; + } + + @Override + public ClientHttpResponse intercept(@NonNull HttpRequest httpRequest, @NonNull byte[] bytes, + @NonNull ClientHttpRequestExecution clientHttpRequestExecution) throws IOException { + + + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.getEnhancedPluginContextFromMetadataContext(); + if (enhancedPluginContext != null) { + pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext); + } + else { + LOG.debug("No exist enhanced plugin context, request:{}", httpRequest.getURI()); + } + + return clientHttpRequestExecution.execute(httpRequest, bytes); + } +} diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisBlockingLoadBalancerClient.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisBlockingLoadBalancerClient.java index aa9a89774..446da964f 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisBlockingLoadBalancerClient.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisBlockingLoadBalancerClient.java @@ -55,8 +55,8 @@ public class PolarisBlockingLoadBalancerClient extends BlockingLoadBalancerClien if (httpRequest == null || enhancedPluginRunner == null) { return delegate.execute(serviceId, request); } - EnhancedRestTemplateWrapInterceptor enhancedRestTemplateWrapInterceptor = new EnhancedRestTemplateWrapInterceptor(enhancedPluginRunner, delegate); - return enhancedRestTemplateWrapInterceptor.intercept(httpRequest, serviceId, null, request); + EnhancedRestTemplateBlockingLoadBalancerClientInterceptor enhancedRestTemplateBlockingLoadBalancerClientInterceptor = new EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(enhancedPluginRunner, delegate); + return enhancedRestTemplateBlockingLoadBalancerClientInterceptor.intercept(httpRequest, serviceId, null, request); } /** @@ -68,7 +68,7 @@ public class PolarisBlockingLoadBalancerClient extends BlockingLoadBalancerClien if (httpRequest == null || serviceInstance == null || enhancedPluginRunner == null) { return delegate.execute(serviceId, serviceInstance, request); } - EnhancedRestTemplateWrapInterceptor enhancedRestTemplateWrapInterceptor = new EnhancedRestTemplateWrapInterceptor(enhancedPluginRunner, delegate); - return enhancedRestTemplateWrapInterceptor.intercept(httpRequest, serviceId, serviceInstance, request); + EnhancedRestTemplateBlockingLoadBalancerClientInterceptor enhancedRestTemplateBlockingLoadBalancerClientInterceptor = new EnhancedRestTemplateBlockingLoadBalancerClientInterceptor(enhancedPluginRunner, delegate); + return enhancedRestTemplateBlockingLoadBalancerClientInterceptor.intercept(httpRequest, serviceId, serviceInstance, request); } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java index 713249bd2..947d6b86c 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/resttemplate/PolarisLoadBalancerRequestTransformer.java @@ -18,6 +18,8 @@ package com.tencent.cloud.rpc.enhancement.instrument.resttemplate; import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestTransformer; @@ -45,6 +47,10 @@ public class PolarisLoadBalancerRequestTransformer implements LoadBalancerReques public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) { if (instance != null) { MetadataContextHolder.get().setLoadbalancer(LOAD_BALANCER_SERVICE_INSTANCE, instance); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.getEnhancedPluginContextFromMetadataContext(); + if (enhancedPluginContext != null) { + enhancedPluginContext.setTargetServiceInstance(instance, request.getURI()); + } } return request; } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/scg/EnhancedGatewayGlobalFilter.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/scg/EnhancedGatewayGlobalFilter.java index 651edac51..20dbc8278 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/scg/EnhancedGatewayGlobalFilter.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/scg/EnhancedGatewayGlobalFilter.java @@ -30,6 +30,7 @@ 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 com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.api.utils.StringUtils; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; @@ -83,7 +84,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered { MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE); - EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext(); EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() .httpHeaders(originExchange.getRequest().getHeaders()) @@ -137,6 +138,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered { enhancedPluginContext.setTargetServiceInstance(null, uri); } } + pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext); }) .doOnSuccess(v -> { MetadataContext metadataContextOnSuccess = originExchange.getAttribute( diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java index e03d2c78a..d46403981 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/instrument/webclient/EnhancedWebClientExchangeFilterFunction.java @@ -21,12 +21,15 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Optional; +import com.tencent.cloud.common.constant.MetadataConstant; +import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.cloud.rpc.enhancement.util.EnhancedPluginUtils; import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import reactor.core.publisher.Mono; @@ -54,13 +57,17 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu @Override public Mono filter(ClientRequest originRequest, ExchangeFunction next) { - EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext(); + EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext(); + + String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE, + MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE); EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder() .httpHeaders(originRequest.headers()) .httpMethod(originRequest.method()) .url(originRequest.url()) .serviceUrl(getServiceUri(originRequest)) + .governanceNamespace(governanceNamespace) .build(); enhancedPluginContext.setRequest(enhancedRequestContext); enhancedPluginContext.setOriginRequest(originRequest); @@ -72,6 +79,7 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu // Run post enhanced plugins. try { pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext); + pluginRunner.run(EnhancedPluginType.Client.BEFORE_CALLING, enhancedPluginContext); } catch (CallAbortedException e) { // Run finally enhanced plugins. diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java index bbc239bcb..5f2826585 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginType.java @@ -29,6 +29,10 @@ public interface EnhancedPluginType { * Pre Client plugin. */ PRE, + /** + * Before calling the Client plugin. + */ + BEFORE_CALLING, /** * Post Client plugin. diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java index f6534770f..72850bc6a 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java @@ -70,7 +70,7 @@ public class PluginOrderConstant { * and * {@link com.tencent.cloud.plugin.trace.TraceClientFinallyEnhancedPlugin}. */ - public static final int TRACE_CLIENT_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 3; + public static final int TRACE_CLIENT_PLUGIN_ORDER = CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER + 3; } public static class ServerPluginOrder { diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java index 1586a056c..11cb2c27a 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/transformer/PolarisInstanceTransformer.java @@ -23,6 +23,8 @@ import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.pojo.PolarisServiceInstance; import com.tencent.polaris.api.pojo.DefaultInstance; import com.tencent.polaris.api.utils.CollectionUtils; +import com.tencent.polaris.api.utils.StringUtils; +import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants; import org.springframework.cloud.client.ServiceInstance; @@ -47,7 +49,16 @@ public class PolarisInstanceTransformer implements InstanceTransformer { } String namespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE, - MetadataConstant.POLARIS_TARGET_NAMESPACE, instance.getNamespace()); + MetadataConstant.POLARIS_TARGET_NAMESPACE); + + if (StringUtils.isBlank(namespace) && serviceInstance.getMetadata() != null && + serviceInstance.getMetadata().containsKey(TsfMetadataConstants.TSF_NAMESPACE_ID)) { + namespace = serviceInstance.getMetadata().get(TsfMetadataConstants.TSF_NAMESPACE_ID); + } + + if (StringUtils.isBlank(namespace)) { + namespace = instance.getNamespace(); + } instance.setNamespace(namespace); } diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/util/EnhancedPluginUtils.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/util/EnhancedPluginUtils.java new file mode 100644 index 000000000..791128c0c --- /dev/null +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/util/EnhancedPluginUtils.java @@ -0,0 +1,54 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 Tencent. 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.util; + +import com.tencent.cloud.common.constant.ContextConstant; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.common.util.MetadataContextUtils; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.polaris.metadata.core.MetadataObjectValue; +import com.tencent.polaris.metadata.core.MetadataType; + +/** + * EnhancedPluginUtils. + * + * @author Shedfree Wu + */ +public final class EnhancedPluginUtils { + + private EnhancedPluginUtils() { + } + + public static EnhancedPluginContext createEnhancedPluginContext() { + EnhancedPluginContext context = new EnhancedPluginContext(); + MetadataContextUtils.putMetadataObjectValue(ContextConstant.ENHANCED_PLUGIN_CONTEXT, context); + return context; + } + + public static EnhancedPluginContext getEnhancedPluginContextFromMetadataContext() { + + MetadataObjectValue enhancedPluginContextObject = MetadataContextHolder.get(). + getMetadataContainer(MetadataType.APPLICATION, true). + getMetadataValue(ContextConstant.ENHANCED_PLUGIN_CONTEXT); + + if (MetadataContextUtils.existMetadataValue(enhancedPluginContextObject)) { + return enhancedPluginContextObject.getObjectValue().get(); + } + return null; + } +}