diff --git a/CHANGELOG.md b/CHANGELOG.md index f83741744..0d8f8a6ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,3 +18,4 @@ - [fix:fix the ratelimit bug](https://github.com/Tencent/spring-cloud-tencent/pull/1389) - [feat:add Tencent Cloud TSF support.](https://github.com/Tencent/spring-cloud-tencent/pull/1391) - [feat:support consul config.](https://github.com/Tencent/spring-cloud-tencent/pull/1394) +- [feat:add trace report support.](https://github.com/Tencent/spring-cloud-tencent/pull/1396) \ No newline at end of file diff --git a/spring-cloud-starter-tencent-all/pom.xml b/spring-cloud-starter-tencent-all/pom.xml index 79bba53e0..767a25866 100644 --- a/spring-cloud-starter-tencent-all/pom.xml +++ b/spring-cloud-starter-tencent-all/pom.xml @@ -49,6 +49,11 @@ com.tencent.cloud spring-cloud-starter-tencent-polaris-contract + + + com.tencent.cloud + spring-cloud-starter-tencent-trace-plugin + diff --git a/spring-cloud-tencent-commons/pom.xml b/spring-cloud-tencent-commons/pom.xml index a667b9831..59daa7efe 100644 --- a/spring-cloud-tencent-commons/pom.xml +++ b/spring-cloud-tencent-commons/pom.xml @@ -78,6 +78,11 @@ true + + com.google.code.gson + gson + + org.springframework.cloud spring-cloud-starter-openfeign diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java index 8c75f5256..b490632fd 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java @@ -181,5 +181,10 @@ public class OrderConstant { * Order of service contract configuration modifier. */ public static Integer SERVICE_CONTRACT_ORDER = Integer.MAX_VALUE - 9; + + /** + * Order of trace configuration modifier. + */ + public static Integer TRACE_ORDER = 2; } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java index 11b667c1a..e43a60f86 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/metadata/MetadataContext.java @@ -137,7 +137,7 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M return values; } - private void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean downstream, Map values) { + public void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean downstream, Map values) { MetadataContainer metadataContainer = getMetadataContainer(metadataType, downstream); for (Map.Entry entry : values.entrySet()) { metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), transitiveType); @@ -258,7 +258,7 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M case FRAGMENT_RAW_TRANSHEADERS: return getMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS, TransitiveType.NONE, false); case FRAGMENT_RAW_TRANSHEADERS_KV: - return getMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS_KV, TransitiveType.PASS_THROUGH, false); + return getMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS_KV, TransitiveType.NONE, false); default: return getMapMetadataAsMap(MetadataType.CUSTOM, fragment, TransitiveType.NONE, false); } @@ -293,7 +293,7 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M putMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS, TransitiveType.NONE, false, context); break; case FRAGMENT_RAW_TRANSHEADERS_KV: - putMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS_KV, TransitiveType.PASS_THROUGH, false, context); + putMapMetadataAsMap(MetadataType.CUSTOM, FRAGMENT_RAW_TRANSHEADERS_KV, TransitiveType.NONE, false, context); break; default: putMapMetadataAsMap(MetadataType.CUSTOM, fragment, TransitiveType.NONE, false, context); diff --git a/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/context/TsfContext.java b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/context/TsfContext.java new file mode 100644 index 000000000..0e7c98a8f --- /dev/null +++ b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/context/TsfContext.java @@ -0,0 +1,78 @@ +/* + * 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 org.springframework.tsf.core.context; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.TransitiveType; + +import org.springframework.tsf.core.entity.Tag; + +public final class TsfContext { + + static final int MAX_KEY_LENGTH = 32; + static final int MAX_VALUE_LENGTH = 128; + + private TsfContext() { + + } + + public static void putTags(Map tagMap, Tag.ControlFlag... flags) { + if (tagMap == null) { + return; + } + MetadataContext tsfCoreContext = MetadataContextHolder.get(); + TransitiveType transitive = TransitiveType.NONE; + if (null != flags) { + for (Tag.ControlFlag flag : flags) { + if (flag == Tag.ControlFlag.TRANSITIVE) { + transitive = TransitiveType.PASS_THROUGH; + break; + } + } + } + for (Map.Entry entry : tagMap.entrySet()) { + validateTag(entry.getKey(), entry.getValue()); + } + tsfCoreContext.putMetadataAsMap(MetadataType.CUSTOM, transitive, false, tagMap); + } + + public static void putTag(String key, String value, Tag.ControlFlag... flags) { + putTags(Collections.singletonMap(key, value), flags); + } + + private static void validateTag(String key, String value) { + int keyLength = key.getBytes(StandardCharsets.UTF_8).length; + int valueLength = value.getBytes(StandardCharsets.UTF_8).length; + + if (keyLength > MAX_KEY_LENGTH) { + throw new RuntimeException(String.format("Key \"%s\" length (after UTF-8 encoding) exceeding limit (%d)", key, + MAX_KEY_LENGTH)); + } + if (valueLength > MAX_VALUE_LENGTH) { + throw new RuntimeException(String.format("Value \"%s\" length (after UTF-8 encoding) exceeding limit (%d)", value, + MAX_VALUE_LENGTH)); + } + } +} diff --git a/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/entity/Tag.java b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/entity/Tag.java new file mode 100644 index 000000000..16d409a0c --- /dev/null +++ b/spring-cloud-tencent-commons/src/main/java/org/springframework/tsf/core/entity/Tag.java @@ -0,0 +1,144 @@ +/* + * 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 org.springframework.tsf.core.entity; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Tag implements Serializable { + + /** + * update version whenever change the content in tag. + */ + public static final int VERSION = 1; + + public enum ControlFlag { + + /** + * tag transitive by all services. + */ + @SerializedName("0") + TRANSITIVE, + + /** + * tag not used in auth. + */ + @SerializedName("1") + NOT_IN_AUTH, + + /** + * tag not used in route. + */ + @SerializedName("2") + NOT_IN_ROUTE, + + /** + * tag not used in trace. + */ + @SerializedName("3") + NOT_IN_SLEUTH, + + /** + * tag not used in lane. + */ + @SerializedName("4") + NOT_IN_LANE, + + /** + * tag not used in unit. + */ + @SerializedName("5") + IN_UNIT + } + + @SerializedName("k") + @Expose + private String key; + + @SerializedName("v") + @Expose + private String value; + + @SerializedName("f") + @Expose + private Set flags = new HashSet<>(); + + public Tag(String key, String value, ControlFlag... flags) { + this.key = key; + this.value = value; + this.flags = new HashSet<>(Arrays.asList(flags)); + } + + public Tag() { + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Set getFlags() { + return flags; + } + + public void setFlags(Set flags) { + this.flags = flags; + } + + @Override + public boolean equals(Object object) { + if (object instanceof Tag) { + Tag tag = (Tag) object; + return (key == null ? tag.key == null : key.equals(tag.key)) + && (flags == null ? tag.flags == null : flags.equals(tag.flags)); + } + return false; + } + + @Override + public int hashCode() { + return (key == null ? 0 : key.hashCode()) + (flags == null ? 0 : flags.hashCode()); + } + + + @Override + public String toString() { + return "Tag{" + + "key='" + key + '\'' + + ", value='" + value + '\'' + + ", flags=" + flags + + '}'; + } +} diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml index f2e7bc65c..98c855809 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -203,6 +203,12 @@ ${revision} + + com.tencent.cloud + spring-cloud-starter-tencent-trace-plugin + ${revision} + + com.google.guava diff --git a/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml index 2be4b3bc1..52c29f727 100644 --- a/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml +++ b/spring-cloud-tencent-examples/lossless-example/lossless-nacos-callee-service/pom.xml @@ -15,7 +15,7 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery - 2023.0.0.0-RC1 + 2022.0.0.0 diff --git a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java index ec939dd17..d5f55a97d 100644 --- a/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java +++ b/spring-cloud-tencent-examples/quickstart-example/quickstart-caller-service/src/main/java/com/tencent/cloud/quickstart/caller/QuickstartCallerController.java @@ -17,9 +17,12 @@ package com.tencent.cloud.quickstart.caller; +import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.core.publisher.Mono; @@ -63,6 +66,8 @@ public class QuickstartCallerController { */ @GetMapping("/feign") public String feign(@RequestParam int value1, @RequestParam int value2) { + MetadataContext metadataContext = MetadataContextHolder.get(); + metadataContext.setTransitiveMetadata(Collections.singletonMap("feign-trace", String.format("%d+%d", value1, value2))); return quickstartCalleeService.sum(value1, value2); } diff --git a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java index 63f4f97f0..cb98fa80f 100644 --- a/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java +++ b/spring-cloud-tencent-examples/tsf-example/consumer-demo/src/main/java/com/tencent/cloud/tsf/demo/consumer/controller/ConsumerController.java @@ -17,10 +17,15 @@ package com.tencent.cloud.tsf.demo.consumer.controller; +import java.util.HashMap; +import java.util.Map; + import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderDemoService; import com.tencent.cloud.tsf.demo.consumer.proxy.ProviderService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.tsf.core.context.TsfContext; +import org.springframework.tsf.core.entity.Tag; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -38,16 +43,31 @@ public class ConsumerController { @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET) public String restProvider(@PathVariable String str) { + TsfContext.putTag("operation", "rest"); + Map mTags = new HashMap<>(); + mTags.put("rest-trace-key1", "value1"); + mTags.put("rest-trace-key2", "value2"); + TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE); return restTemplate.getForObject("http://provider-demo/echo/" + str, String.class); } @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET) public String feignProvider(@PathVariable String str) { + TsfContext.putTag("operation", "feign"); + Map mTags = new HashMap<>(); + mTags.put("feign-trace-key1", "value1"); + mTags.put("feign-trace-key2", "value2"); + TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE); return providerDemoService.echo(str); } @RequestMapping(value = "/echo-feign-url/{str}", method = RequestMethod.GET) public String feignUrlProvider(@PathVariable String str) { + TsfContext.putTag("operation", "feignUrl"); + Map mTags = new HashMap<>(); + mTags.put("feignUrl-trace-key1", "value1"); + mTags.put("feignUrl-trace-key2", "value2"); + TsfContext.putTags(mTags, Tag.ControlFlag.TRANSITIVE); return providerService.echo(str); } } diff --git a/spring-cloud-tencent-plugin-starters/pom.xml b/spring-cloud-tencent-plugin-starters/pom.xml index 5debf6360..702dfeca4 100644 --- a/spring-cloud-tencent-plugin-starters/pom.xml +++ b/spring-cloud-tencent-plugin-starters/pom.xml @@ -20,6 +20,7 @@ spring-cloud-starter-tencent-discovery-adapter-plugin spring-cloud-tencent-lossless-plugin spring-cloud-starter-tencent-threadlocal-plugin + spring-cloud-starter-tencent-trace-plugin diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/pom.xml b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/pom.xml new file mode 100644 index 000000000..99fe4f187 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/pom.xml @@ -0,0 +1,24 @@ + + + spring-cloud-tencent-plugin-starters + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + spring-cloud-starter-tencent-trace-plugin + Spring Cloud Tencent Trace Plugin + + + + + com.tencent.cloud + spring-cloud-tencent-rpc-enhancement + + + com.tencent.polaris + trace-otel + + + diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/SpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/SpanAttributesProvider.java new file mode 100644 index 000000000..ed7b2d459 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/SpanAttributesProvider.java @@ -0,0 +1,28 @@ +/* + * 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.plugin.trace; + +import java.util.Map; + +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; + +public interface SpanAttributesProvider { + + Map getConsumerSpanAttributes(EnhancedPluginContext context); +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientMetadataEnhancedPlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientMetadataEnhancedPlugin.java new file mode 100644 index 000000000..dc61810a4 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceClientMetadataEnhancedPlugin.java @@ -0,0 +1,85 @@ +/* + * 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.plugin.trace; + +import java.util.HashMap; +import java.util.Map; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +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 TraceClientMetadataEnhancedPlugin implements EnhancedPlugin { + + private final PolarisSDKContextManager polarisSDKContextManager; + + private final SpanAttributesProvider spanAttributesProvider; + + public TraceClientMetadataEnhancedPlugin(PolarisSDKContextManager polarisSDKContextManager, SpanAttributesProvider spanAttributesProvider) { + this.polarisSDKContextManager = polarisSDKContextManager; + this.spanAttributesProvider = spanAttributesProvider; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Client.PRE; + } + + @Override + public void run(EnhancedPluginContext context) throws Throwable { + AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI(); + Map attributes = new HashMap<>(); + if (null != spanAttributesProvider) { + Map additionalAttributes = spanAttributesProvider.getConsumerSpanAttributes(context); + if (CollectionUtils.isNotEmpty(additionalAttributes)) { + attributes.putAll(additionalAttributes); + } + } + MetadataContext metadataContext = MetadataContextHolder.get(); + Map transitiveCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); + if (CollectionUtils.isNotEmpty(transitiveCustomAttributes)) { + for (Map.Entry entry : transitiveCustomAttributes.entrySet()) { + attributes.put("custom." + entry.getKey(), entry.getValue()); + } + } + Map disposableCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE); + if (CollectionUtils.isNotEmpty(disposableCustomAttributes)) { + for (Map.Entry entry : disposableCustomAttributes.entrySet()) { + attributes.put("custom." + entry.getKey(), entry.getValue()); + } + } + TraceAttributes traceAttributes = new TraceAttributes(); + traceAttributes.setAttributes(attributes); + traceAttributes.setAttributeLocation(TraceAttributes.AttributeLocation.SPAN); + assemblyAPI.updateTraceAttributes(traceAttributes); + } + + @Override + public int getOrder() { + return PluginOrderConstant.ClientPluginOrder.CONSUMER_TRACE_METADATA_PLUGIN_ORDER; + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerMetadataEnhancedPlugin.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerMetadataEnhancedPlugin.java new file mode 100644 index 000000000..6525ec8e4 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/TraceServerMetadataEnhancedPlugin.java @@ -0,0 +1,84 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + +package com.tencent.cloud.plugin.trace; + +import java.util.HashMap; +import java.util.Map; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.metadata.MetadataContextHolder; +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 TraceServerMetadataEnhancedPlugin implements EnhancedPlugin { + + private final PolarisSDKContextManager polarisSDKContextManager; + + private final SpanAttributesProvider spanAttributesProvider; + + public TraceServerMetadataEnhancedPlugin(PolarisSDKContextManager polarisSDKContextManager, SpanAttributesProvider spanAttributesProvider) { + this.polarisSDKContextManager = polarisSDKContextManager; + this.spanAttributesProvider = spanAttributesProvider; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Server.PRE; + } + + @Override + public void run(EnhancedPluginContext context) throws Throwable { + AssemblyAPI assemblyAPI = polarisSDKContextManager.getAssemblyAPI(); + Map attributes = new HashMap<>(); + if (null != spanAttributesProvider) { + Map additionalAttributes = spanAttributesProvider.getConsumerSpanAttributes(context); + if (CollectionUtils.isNotEmpty(additionalAttributes)) { + attributes.putAll(additionalAttributes); + } + } + MetadataContext metadataContext = MetadataContextHolder.get(); + Map transitiveCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); + if (CollectionUtils.isNotEmpty(transitiveCustomAttributes)) { + for (Map.Entry entry : transitiveCustomAttributes.entrySet()) { + attributes.put("custom." + entry.getKey(), entry.getValue()); + } + } + Map disposableCustomAttributes = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE); + if (CollectionUtils.isNotEmpty(disposableCustomAttributes)) { + for (Map.Entry entry : disposableCustomAttributes.entrySet()) { + attributes.put("custom." + entry.getKey(), entry.getValue()); + } + } + TraceAttributes traceAttributes = new TraceAttributes(); + traceAttributes.setAttributes(attributes); + traceAttributes.setAttributeLocation(TraceAttributes.AttributeLocation.SPAN); + assemblyAPI.updateTraceAttributes(traceAttributes); + } + + @Override + public int getOrder() { + return PluginOrderConstant.ServerPluginOrder.PROVIDER_TRACE_METADATA_PLUGIN_ORDER; + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifier.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifier.java new file mode 100644 index 000000000..72370839a --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifier.java @@ -0,0 +1,41 @@ +/* + * 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.plugin.trace.config; + +import com.tencent.cloud.common.constant.OrderConstant; +import com.tencent.cloud.polaris.context.PolarisConfigModifier; +import com.tencent.polaris.factory.config.ConfigurationImpl; + +/** + * Spring Cloud Tencent config Override polaris trace config. + * + * @author andrew 2024-06-18 + */ +public class TraceConfigModifier implements PolarisConfigModifier { + + @Override + public void modify(ConfigurationImpl configuration) { + configuration.getGlobal().getTraceReporter().setEnable(true); + } + + @Override + public int getOrder() { + return OrderConstant.Modifier.TRACE_ORDER; + } +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifierAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifierAutoConfiguration.java new file mode 100644 index 000000000..c9e354048 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifierAutoConfiguration.java @@ -0,0 +1,37 @@ +/* + * 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.plugin.trace.config; + +import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisEnabled +@ConditionalOnProperty(value = "spring.cloud.polaris.trace.enabled", matchIfMissing = true) +public class TraceConfigModifierAutoConfiguration { + + @Bean + public TraceConfigModifier traceConfigModifier() { + return new TraceConfigModifier(); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifierBootstrapAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifierBootstrapAutoConfiguration.java new file mode 100644 index 000000000..4f0a87bc7 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceConfigModifierBootstrapAutoConfiguration.java @@ -0,0 +1,30 @@ +/* + * 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.plugin.trace.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration(proxyBeanMethods = false) +@ConditionalOnProperty("spring.cloud.polaris.enabled") +@Import(TraceConfigModifierAutoConfiguration.class) +public class TraceConfigModifierBootstrapAutoConfiguration { + +} 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 new file mode 100644 index 000000000..932cd1421 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/config/TraceEnhancedPluginAutoConfiguration.java @@ -0,0 +1,50 @@ +/* + * 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.plugin.trace.config; + +import com.tencent.cloud.plugin.trace.SpanAttributesProvider; +import com.tencent.cloud.plugin.trace.TraceClientMetadataEnhancedPlugin; +import com.tencent.cloud.plugin.trace.TraceServerMetadataEnhancedPlugin; +import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled; +import com.tencent.cloud.polaris.context.PolarisSDKContextManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration(proxyBeanMethods = false) +@ConditionalOnPolarisEnabled +@ConditionalOnProperty(value = "spring.cloud.polaris.trace.enabled", matchIfMissing = true) +public class TraceEnhancedPluginAutoConfiguration { + + @Bean + public TraceClientMetadataEnhancedPlugin traceClientMetadataEnhancedPlugin( + PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) SpanAttributesProvider spanAttributesProvider) { + return new TraceClientMetadataEnhancedPlugin(polarisSDKContextManager, spanAttributesProvider); + } + + @Bean + public TraceServerMetadataEnhancedPlugin traceServerMetadataEnhancedPlugin( + PolarisSDKContextManager polarisSDKContextManager, @Autowired(required = false) SpanAttributesProvider spanAttributesProvider) { + return new TraceServerMetadataEnhancedPlugin(polarisSDKContextManager, spanAttributesProvider); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java new file mode 100644 index 000000000..d4bc6882d --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfSpanAttributesProvider.java @@ -0,0 +1,52 @@ +/* + * 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.plugin.trace.tsf; + +import java.util.HashMap; +import java.util.Map; + +import com.tencent.cloud.common.tsf.TsfConstant; +import com.tencent.cloud.plugin.trace.SpanAttributesProvider; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.polaris.api.utils.CollectionUtils; +import com.tencent.polaris.api.utils.StringUtils; + +import org.springframework.cloud.client.ServiceInstance; + +public class TsfSpanAttributesProvider implements SpanAttributesProvider { + + @Override + public Map getConsumerSpanAttributes(EnhancedPluginContext context) { + Map attributes = new HashMap<>(); + if (null != context.getRequest().getUrl()) { + attributes.put("remoteInterface", context.getRequest().getUrl().getPath()); + } + ServiceInstance targetServiceInstance = context.getTargetServiceInstance(); + if (null != targetServiceInstance && CollectionUtils.isNotEmpty(targetServiceInstance.getMetadata())) { + String nsId = targetServiceInstance.getMetadata().get(TsfConstant.TSF_NAMESPACE_ID); + attributes.put("remote.namespace-id", StringUtils.defaultString(nsId)); + String groupId = targetServiceInstance.getMetadata().get(TsfConstant.TSF_GROUP_ID); + attributes.put("remote.group-id", StringUtils.defaultString(groupId)); + String applicationId = targetServiceInstance.getMetadata().get(TsfConstant.TSF_APPLICATION_ID); + attributes.put("remote.application-id", StringUtils.defaultString(applicationId)); + } + return attributes; + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfTracePropertiesAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfTracePropertiesAutoConfiguration.java new file mode 100644 index 000000000..3b5b102f4 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/java/com/tencent/cloud/plugin/trace/tsf/TsfTracePropertiesAutoConfiguration.java @@ -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.plugin.trace.tsf; + +import com.tencent.cloud.common.tsf.ConditionalOnTsfEnabled; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@ConditionalOnTsfEnabled +@ConditionalOnProperty(value = "spring.cloud.polaris.trace.enabled", matchIfMissing = true) +public class TsfTracePropertiesAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public TsfSpanAttributesProvider tsfClientSpanAttributesProvider() { + return new TsfSpanAttributesProvider(); + } + +} diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..eb958b7e9 --- /dev/null +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-trace-plugin/src/main/resources/META-INF/spring.factories @@ -0,0 +1,6 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.tencent.cloud.plugin.trace.config.TraceConfigModifierAutoConfiguration,\ + com.tencent.cloud.plugin.trace.config.TraceEnhancedPluginAutoConfiguration,\ + com.tencent.cloud.plugin.trace.tsf.TsfTracePropertiesAutoConfiguration +org.springframework.cloud.bootstrap.BootstrapConfiguration=\ + com.tencent.cloud.plugin.trace.config.TraceConfigModifierBootstrapAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-tencent-polaris-context/pom.xml b/spring-cloud-tencent-polaris-context/pom.xml index 8f0f84e8c..b24d40d89 100644 --- a/spring-cloud-tencent-polaris-context/pom.xml +++ b/spring-cloud-tencent-polaris-context/pom.xml @@ -49,6 +49,84 @@ + + com.tencent.polaris + polaris-circuitbreaker-factory + + + com.tencent.polaris + router-rule + + + com.tencent.polaris + router-nearby + + + com.tencent.polaris + router-metadata + + + com.tencent.polaris + circuitbreaker-errrate + + + com.tencent.polaris + circuitbreaker-errcount + + + com.tencent.polaris + circuitbreaker-composite + + + com.tencent.polaris + stat-prometheus + + + com.tencent.polaris + healthchecker-http + + + com.tencent.polaris + healthchecker-tcp + + + com.tencent.polaris + healthchecker-udp + + + + + + com.tencent.polaris + polaris-ratelimit-factory + + + com.tencent.polaris + router-rule + + + com.tencent.polaris + router-nearby + + + com.tencent.polaris + router-metadata + + + com.tencent.polaris + ratelimiter-reject + + + com.tencent.polaris + ratelimiter-unirate + + + com.tencent.polaris + stat-prometheus + + + + com.tencent.polaris polaris-client 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 eff88f13a..f839e1dc5 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 @@ -20,6 +20,7 @@ package com.tencent.cloud.rpc.enhancement.plugin; import org.springframework.core.Ordered; + /** * PluginOrderConstant. * @@ -58,5 +59,21 @@ public class PluginOrderConstant { * {@link com.tencent.cloud.metadata.core.EncodeTransferMedataRestTemplateEnhancedPlugin}. */ public static final int CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 10; + + /** + * order for + * {@link com.tencent.cloud.plugin.trace.TraceClientMetadataEnhancedPlugin}. + */ + public static final int CONSUMER_TRACE_METADATA_PLUGIN_ORDER = CONSUMER_TRANSFER_METADATA_PLUGIN_ORDER - 1; + } + + public static class ServerPluginOrder { + + /** + * order for + * {@link com.tencent.cloud.plugin.trace.TraceServerMetadataEnhancedPlugin}. + */ + public static final int PROVIDER_TRACE_METADATA_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1; } + }