From b0cc91382c399cb52454cdf575d664de9a951f2e Mon Sep 17 00:00:00 2001 From: Evan <31562192+EvanLjp@users.noreply.github.com> Date: Sat, 16 Jan 2021 09:04:01 +0800 Subject: [PATCH] export the segmentId and spanId in toolkit (#6213) --- CHANGES.md | 1 + .../apm/toolkit/trace/TraceContext.java | 18 +++++++ .../core/context/AbstractTracerContext.java | 14 ++++++ .../agent/core/context/ContextManager.java | 26 +++++++--- .../core/context/IgnoredTracerContext.java | 13 ++++- .../agent/core/context/TracingContext.java | 10 ++++ .../trace/SegmentIDInterceptor.java | 49 +++++++++++++++++++ .../activation/trace/SpanIDInterceptor.java | 49 +++++++++++++++++++ .../trace/TraceContextActivation.java | 45 +++++++++++++++-- ...terceptor.java => TraceIDInterceptor.java} | 4 +- .../java-agent/Application-toolkit-trace.md | 17 +++++++ .../config/expectedData.yaml | 3 ++ .../apm/toolkit/trace/TraceContext.java | 18 +++++++ .../toolkit/controller/TestController.java | 5 +- 14 files changed, 258 insertions(+), 14 deletions(-) create mode 100644 apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SegmentIDInterceptor.java create mode 100644 apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SpanIDInterceptor.java rename apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/{TraceContextInterceptor.java => TraceIDInterceptor.java} (94%) diff --git a/CHANGES.md b/CHANGES.md index ca962c525..91a8d4eaf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -32,6 +32,7 @@ Release Notes. * Fix bug that rocketmq-plugin set the wrong tag. * Fix duplicated `EnhancedInstance` interface added. * Fix thread leaks caused by the elasticsearch-6.x-plugin plugin. +* Support reading segmentId and spanId with toolkit. #### OAP-Backend diff --git a/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java b/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java index c846f44e0..9c1f41d59 100644 --- a/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java +++ b/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java @@ -36,6 +36,24 @@ public class TraceContext { return ""; } + /** + * Try to get the segmentId of current trace context. + * + * @return segmentId, if it exists, or empty {@link String}. + */ + public static String segmentId() { + return ""; + } + + /** + * Try to get the spanId of current trace context. + * + * @return spanId, if it exists, or empty {@link String}. + */ + public static String spanId() { + return ""; + } + /** * Try to get the custom value from trace context. * diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java index 2a66a7713..966418a67 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java @@ -62,6 +62,20 @@ public interface AbstractTracerContext { */ String getReadablePrimaryTraceId(); + /** + * Get the current segment id, if needEnhance. How to build, depends on the implementation. + * + * @return the string represents the id. + */ + String getSegmentId(); + + /** + * Get the active span id, if needEnhance. How to build, depends on the implementation. + * + * @return the string represents the id. + */ + String getSpanId(); + /** * Create an entry span * diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java index 39190c784..eb32d90e0 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.agent.core.context; +import java.util.Objects; import org.apache.skywalking.apm.agent.core.boot.BootService; import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; @@ -38,6 +39,7 @@ import static org.apache.skywalking.apm.agent.core.conf.Config.Agent.OPERATION_N *

Also, {@link ContextManager} delegates to all {@link AbstractTracerContext}'s major methods. */ public class ContextManager implements BootService { + private static final String EMPTY_TRACE_CONTEXT_ID = "N/A"; private static final ILog LOGGER = LogManager.getLogger(ContextManager.class); private static ThreadLocal CONTEXT = new ThreadLocal(); private static ThreadLocal RUNTIME_CONTEXT = new ThreadLocal(); @@ -71,12 +73,24 @@ public class ContextManager implements BootService { * @return the first global trace id if needEnhance. Otherwise, "N/A". */ public static String getGlobalTraceId() { - AbstractTracerContext segment = CONTEXT.get(); - if (segment == null) { - return "N/A"; - } else { - return segment.getReadablePrimaryTraceId(); - } + AbstractTracerContext context = CONTEXT.get(); + return Objects.nonNull(context) ? context.getReadablePrimaryTraceId() : EMPTY_TRACE_CONTEXT_ID; + } + + /** + * @return the current segment id if needEnhance. Otherwise, "N/A". + */ + public static String getSegmentId() { + AbstractTracerContext context = CONTEXT.get(); + return Objects.nonNull(context) ? context.getSegmentId() : EMPTY_TRACE_CONTEXT_ID; + } + + /** + * @return the current span id if needEnhance. Otherwise, "N/A". + */ + public static String getSpanId() { + AbstractTracerContext context = CONTEXT.get(); + return Objects.nonNull(context) ? context.getSpanId() : EMPTY_TRACE_CONTEXT_ID; } public static AbstractSpan createEntrySpan(String operationName, ContextCarrier carrier) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java index d9ac90edb..3f9531e77 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java @@ -31,6 +31,7 @@ import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan; */ public class IgnoredTracerContext implements AbstractTracerContext { private static final NoopSpan NOOP_SPAN = new NoopSpan(); + private static final String IGNORE_TRACE = "Ignored_Trace"; private final CorrelationContext correlationContext; private final ExtensionContext extensionContext; @@ -65,7 +66,17 @@ public class IgnoredTracerContext implements AbstractTracerContext { @Override public String getReadablePrimaryTraceId() { - return "Ignored_Trace"; + return IGNORE_TRACE; + } + + @Override + public String getSegmentId() { + return IGNORE_TRACE; + } + + @Override + public String getSpanId() { + return IGNORE_TRACE; } @Override diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java index 9026d035d..17733f847 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java @@ -243,6 +243,16 @@ public class TracingContext implements AbstractTracerContext { return segment.getRelatedGlobalTraces().get(0); } + @Override + public String getSegmentId() { + return segment.getTraceSegmentId(); + } + + @Override + public String getSpanId() { + return String.valueOf(activeSpan().getSpanId()); + } + /** * Create an entry span * diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SegmentIDInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SegmentIDInterceptor.java new file mode 100644 index 000000000..d49f2c6d2 --- /dev/null +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SegmentIDInterceptor.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.skywalking.apm.toolkit.activation.trace; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; + +public class SegmentIDInterceptor implements StaticMethodsAroundInterceptor { + + private static final ILog LOGGER = LogManager.getLogger(SegmentIDInterceptor.class); + + @Override + public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + MethodInterceptResult result) { + result.defineReturnValue(ContextManager.getSegmentId()); + } + + @Override + public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + Object ret) { + return ret; + } + + @Override + public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + Throwable t) { + LOGGER.error("Failed to getDefault segment Id.", t); + } +} diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SpanIDInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SpanIDInterceptor.java new file mode 100644 index 000000000..aad91ef1e --- /dev/null +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/SpanIDInterceptor.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.apache.skywalking.apm.toolkit.activation.trace; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; + +public class SpanIDInterceptor implements StaticMethodsAroundInterceptor { + + private static final ILog LOGGER = LogManager.getLogger(SpanIDInterceptor.class); + + @Override + public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + MethodInterceptResult result) { + result.defineReturnValue(ContextManager.getSpanId()); + } + + @Override + public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + Object ret) { + return ret; + } + + @Override + public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + Throwable t) { + LOGGER.error("Failed to getDefault span Id.", t); + } +} diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextActivation.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextActivation.java index 80c34eb6b..4c273a590 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextActivation.java +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextActivation.java @@ -35,9 +35,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named; */ public class TraceContextActivation extends ClassStaticMethodsEnhancePluginDefine { - public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.toolkit.activation.trace.TraceContextInterceptor"; + public static final String TRACE_ID_INTERCEPT_CLASS = "org.apache.skywalking.apm.toolkit.activation.trace.TraceIDInterceptor"; + public static final String SEGMENT_ID_INTERCEPT_CLASS = "org.apache.skywalking.apm.toolkit.activation.trace.SegmentIDInterceptor"; + public static final String SPAN_ID_INTERCEPT_CLASS = "org.apache.skywalking.apm.toolkit.activation.trace.SpanIDInterceptor"; public static final String ENHANCE_CLASS = "org.apache.skywalking.apm.toolkit.trace.TraceContext"; - public static final String ENHANCE_METHOD = "traceId"; + public static final String ENHANCE_TRACE_ID_METHOD = "traceId"; + public static final String ENHANCE_SEGMENT_ID_METHOD = "segmentId"; + public static final String ENHANCE_SPAN_ID_METHOD = "spanId"; public static final String ENHANCE_GET_CORRELATION_METHOD = "getCorrelation"; public static final String INTERCEPT_GET_CORRELATION_CLASS = "org.apache.skywalking.apm.toolkit.activation.trace.CorrelationContextGetInterceptor"; public static final String ENHANCE_PUT_CORRELATION_METHOD = "putCorrelation"; @@ -61,12 +65,12 @@ public class TraceContextActivation extends ClassStaticMethodsEnhancePluginDefin new StaticMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { - return named(ENHANCE_METHOD); + return named(ENHANCE_TRACE_ID_METHOD); } @Override public String getMethodsInterceptor() { - return INTERCEPT_CLASS; + return TRACE_ID_INTERCEPT_CLASS; } @Override @@ -74,6 +78,39 @@ public class TraceContextActivation extends ClassStaticMethodsEnhancePluginDefin return false; } }, + new StaticMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_SEGMENT_ID_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return SEGMENT_ID_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new StaticMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_SPAN_ID_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return SPAN_ID_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new StaticMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceIDInterceptor.java similarity index 94% rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextInterceptor.java rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceIDInterceptor.java index debc6863b..aead75726 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceContextInterceptor.java +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceIDInterceptor.java @@ -25,9 +25,9 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMet import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; -public class TraceContextInterceptor implements StaticMethodsAroundInterceptor { +public class TraceIDInterceptor implements StaticMethodsAroundInterceptor { - private static final ILog LOGGER = LogManager.getLogger(TraceContextInterceptor.class); + private static final ILog LOGGER = LogManager.getLogger(TraceIDInterceptor.class); @Override public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md index 8d4e95af7..bb1de05c0 100644 --- a/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md +++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md @@ -14,6 +14,23 @@ import TraceContext; modelAndView.addObject("traceId", TraceContext.traceId()); ``` +* Use `TraceContext.segmentId()` API to obtain segmentId. +```java +import TraceContext; +... + +modelAndView.addObject("segmentId", TraceContext.segmentId()); +``` + +* Use `TraceContext.spanId()` API to obtain spanId. +```java +import TraceContext; +... + +modelAndView.addObject("spanId", TraceContext.spanId()); +``` + + _Sample codes only_ * Add `@Trace` to any method you want to trace. After that, you can see the span in the Stack. diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml b/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml index 2a574f1a7..2bcc1cd19 100644 --- a/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml @@ -143,6 +143,9 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/apm-toolkit-trace-scenario/case/tool-kit'} - {key: http.method, value: GET} + - {key: traceID, value: not null} + - {key: segmentID, value: not null} + - {key: spanID, value: not null} skipAnalysis: 'true' refs: - {parentEndpoint: /app, networkAddress: '127.0.0.1:8080', refType: CrossProcess, diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java index c846f44e0..9c1f41d59 100644 --- a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java +++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/trace/TraceContext.java @@ -36,6 +36,24 @@ public class TraceContext { return ""; } + /** + * Try to get the segmentId of current trace context. + * + * @return segmentId, if it exists, or empty {@link String}. + */ + public static String segmentId() { + return ""; + } + + /** + * Try to get the spanId of current trace context. + * + * @return spanId, if it exists, or empty {@link String}. + */ + public static String spanId() { + return ""; + } + /** * Try to get the custom value from trace context. * diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/apache/skywalking/apm/testcase/toolkit/controller/TestController.java b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/apache/skywalking/apm/testcase/toolkit/controller/TestController.java index b581cfc84..baa8d1cde 100644 --- a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/apache/skywalking/apm/testcase/toolkit/controller/TestController.java +++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/apache/skywalking/apm/testcase/toolkit/controller/TestController.java @@ -59,6 +59,9 @@ public class TestController { testService.testTagAnnotation("testTagAnnotationParam1", "testTagAnnotationParam2"); testService.testTagAnnotationReturnInfo("zhangsan", 15); TraceContext.putCorrelation(CORRELATION_CONTEXT_KEY, CORRELATION_CONTEXT_VALUE); + ActiveSpan.tag("traceID", TraceContext.traceId()); + ActiveSpan.tag("segmentID", TraceContext.segmentId()); + ActiveSpan.tag("spanID", TraceContext.spanId()); testService.asyncCallable(() -> { visit("http://localhost:8080/apm-toolkit-trace-scenario/case/asyncVisit/callable"); return true; @@ -83,7 +86,7 @@ public class TestController { MeterFactory.counter("test_counter").tag("ck1", "cv1").build().increment(2d); MeterFactory.gauge("test_gauge", () -> 1d).tag("gk1", "gv1").build(); MeterFactory.histogram("test_histogram").tag("hk1", "hv1").steps(Arrays.asList(1d, 5d, 10d)) - .build().addValue(4d); + .build().addValue(4d); return SUCCESS; }