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 d6094921f..0a5a96d00 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 @@ -224,4 +224,5 @@ public class ContextManager implements BootService { return runtimeContext; } + } 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 d73998a4a..a31145ef7 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 @@ -39,6 +39,7 @@ import org.apache.skywalking.apm.agent.core.dictionary.DictionaryManager; import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil; 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.profile.ProfileStatusReference; import org.apache.skywalking.apm.agent.core.profile.ProfileTaskExecutionService; import org.apache.skywalking.apm.agent.core.sampling.SamplingService; import org.apache.skywalking.apm.util.StringUtil; @@ -106,9 +107,9 @@ public class TracingContext implements AbstractTracerContext { private final long createTime; /** - * profiling status + * profile status */ - private volatile boolean profiling; + private final ProfileStatusReference profileStatus; /** * Initialize all fields with default value. @@ -128,7 +129,7 @@ public class TracingContext implements AbstractTracerContext { if (PROFILE_TASK_EXECUTION_SERVICE == null) { PROFILE_TASK_EXECUTION_SERVICE = ServiceManager.INSTANCE.findService(ProfileTaskExecutionService.class); } - this.profiling = PROFILE_TASK_EXECUTION_SERVICE.addProfiling(this, segment.getTraceSegmentId(), firstOPName); + this.profileStatus = PROFILE_TASK_EXECUTION_SERVICE.addProfiling(this, segment.getTraceSegmentId(), firstOPName); } /** @@ -521,7 +522,7 @@ public class TracingContext implements AbstractTracerContext { return; } - profiling = PROFILE_TASK_EXECUTION_SERVICE.profilingRecheck(this, segment.getTraceSegmentId(), operationName); + PROFILE_TASK_EXECUTION_SERVICE.profilingRecheck(this, segment.getTraceSegmentId(), operationName); } /** @@ -688,8 +689,7 @@ public class TracingContext implements AbstractTracerContext { return this.createTime; } - public boolean isProfiling() { - return this.profiling; + public ProfileStatusReference profileStatus() { + return this.profileStatus; } - } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java index 88ee2127d..75946d3aa 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java @@ -126,4 +126,9 @@ public interface AbstractSpan extends AsyncSpan { AbstractSpan start(long startTime); AbstractSpan setPeer(String remotePeer); + + /** + * @return true if the span's owner(tracing context main thread) is been profiled. + */ + boolean isProfiling(); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java index fb170abd0..001f93434 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java @@ -358,4 +358,9 @@ public abstract class AbstractTracingSpan implements AbstractSpan { isAsyncStopped = true; return this; } + + @Override + public boolean isProfiling() { + return this.owner.profileStatus().isProfiling(); + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java index c08db0eec..234af2d72 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java @@ -129,6 +129,11 @@ public class NoopSpan implements AbstractSpan { return this; } + @Override + public boolean isProfiling() { + return false; + } + @Override public AbstractSpan prepareForAsync() { return this; diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileStatus.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileStatus.java new file mode 100644 index 000000000..1fab05251 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileStatus.java @@ -0,0 +1,46 @@ +/* + * 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.agent.core.profile; + +/** + * Profile status, include entire profile cycle + */ +public enum ProfileStatus { + /** + * No profile + */ + NONE, + + /** + * Prepare to profile, until {@link ProfileTask#getMinDurationThreshold()} reached, + * Once the status changed to profiling, the thread snapshot is officially started + */ + PENDING, + + /** + * Profile operation has been started. + */ + PROFILING, + + /** + * The current {@link org.apache.skywalking.apm.agent.core.context.TracingContext} has finished, + * or the current thread isn't available. + */ + STOPPED +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileStatusReference.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileStatusReference.java new file mode 100644 index 000000000..7d1149fc7 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileStatusReference.java @@ -0,0 +1,69 @@ +/* + * 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.agent.core.profile; + +/** + * Wrapper {@link ProfileStatus}, make sure {@link org.apache.skywalking.apm.agent.core.context.TracingContext} with {@link ThreadProfiler} have same reference with {@link ProfileStatus}, + * And only the profile module could change the status + */ +public class ProfileStatusReference { + + private volatile ProfileStatus status; + + private ProfileStatusReference(ProfileStatus status) { + this.status = status; + } + + /** + * Create with not watching + */ + public static ProfileStatusReference createWithNone() { + return new ProfileStatusReference(ProfileStatus.NONE); + } + + /** + * Create with pending to profile + */ + public static ProfileStatusReference createWithPending() { + return new ProfileStatusReference(ProfileStatus.PENDING); + } + + public ProfileStatus get() { + return this.status; + } + + /** + * The profile monitoring is watching, wait for some profile conditions. + */ + public boolean isBeingWatched() { + return this.status != ProfileStatus.NONE; + } + + public boolean isProfiling() { + return this.status == ProfileStatus.PROFILING; + } + + /** + * Update status, only access with profile module + */ + void updateStatus(ProfileStatus status) { + this.status = status; + } + +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionContext.java index bb1949ff4..d1f5caf4c 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionContext.java @@ -74,48 +74,49 @@ public class ProfileTaskExecutionContext { * * @return is add profile success */ - public boolean attemptProfiling(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { + public ProfileStatusReference attemptProfiling(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { // check has available slot final int usingSlotCount = currentProfilingCount.get(); if (usingSlotCount >= Config.Profile.MAX_PARALLEL) { - return false; + return ProfileStatusReference.createWithNone(); } // check first operation name matches if (!Objects.equals(task.getFistSpanOPName(), firstSpanOPName)) { - return false; + return ProfileStatusReference.createWithNone(); } // if out limit started profiling count then stop add profiling if (totalStartedProfilingCount.get() > task.getMaxSamplingCount()) { - return false; + return ProfileStatusReference.createWithNone(); } // try to occupy slot if (!currentProfilingCount.compareAndSet(usingSlotCount, usingSlotCount + 1)) { - return false; + return ProfileStatusReference.createWithNone(); } final ThreadProfiler threadProfiler = new ThreadProfiler(tracingContext, traceSegmentId, Thread.currentThread(), this); int slotLength = profilingSegmentSlots.length(); for (int slot = 0; slot < slotLength; slot++) { if (profilingSegmentSlots.compareAndSet(slot, null, threadProfiler)) { - break; + return threadProfiler.profilingStatus(); } } - return true; + return ProfileStatusReference.createWithNone(); } /** * profiling recheck */ - public boolean profilingRecheck(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { + public void profilingRecheck(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { // if started, keep profiling - if (tracingContext.isProfiling()) { - return true; + if (tracingContext.profileStatus().isBeingWatched()) { + return; } - return attemptProfiling(tracingContext, traceSegmentId, firstSpanOPName); + // update profiling status + tracingContext.profileStatus().updateStatus(attemptProfiling(tracingContext, traceSegmentId, firstSpanOPName).get()); } /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionService.java index afe840e5e..308b20c76 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionService.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionService.java @@ -91,11 +91,11 @@ public class ProfileTaskExecutionService implements BootService, TracingThreadLi /** * check and add {@link TracingContext} profiling */ - public boolean addProfiling(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { + public ProfileStatusReference addProfiling(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { // get current profiling task, check need profiling final ProfileTaskExecutionContext executionContext = taskExecutionContext.get(); if (executionContext == null) { - return false; + return ProfileStatusReference.createWithNone(); } return executionContext.attemptProfiling(tracingContext, traceSegmentId, firstSpanOPName); @@ -104,14 +104,14 @@ public class ProfileTaskExecutionService implements BootService, TracingThreadLi /** * Re-check current trace need profiling, in case that third-party plugins change the operation name. */ - public boolean profilingRecheck(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { + public void profilingRecheck(TracingContext tracingContext, ID traceSegmentId, String firstSpanOPName) { // get current profiling task, check need profiling final ProfileTaskExecutionContext executionContext = taskExecutionContext.get(); if (executionContext == null) { - return false; + return; } - return executionContext.profilingRecheck(tracingContext, traceSegmentId, firstSpanOPName); + executionContext.profilingRecheck(tracingContext, traceSegmentId, firstSpanOPName); } /** @@ -247,7 +247,7 @@ public class ProfileTaskExecutionService implements BootService, TracingThreadLi @Override public void afterMainThreadFinish(TracingContext tracingContext) { - if (tracingContext.isProfiling()) { + if (tracingContext.profileStatus().isBeingWatched()) { // stop profiling tracing context ProfileTaskExecutionContext currentExecutionContext = taskExecutionContext.get(); if (currentExecutionContext != null) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileThread.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileThread.java index b8c6e442e..ba0b7ce9c 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileThread.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileThread.java @@ -81,9 +81,9 @@ public class ProfileThread implements Runnable { continue; } - switch (currentProfiler.profilingStatus()) { + switch (currentProfiler.profilingStatus().get()) { - case READY: + case PENDING: // check tracing context running time currentProfiler.startProfilingIfNeed(); break; diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ThreadProfiler.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ThreadProfiler.java index b860b3688..8587a973d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ThreadProfiler.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ThreadProfiler.java @@ -42,7 +42,7 @@ public class ThreadProfiler { private long profilingMaxTimeMills; // after min duration threshold check, it will start dump - private ProfilingStatus profilingStatus = ProfilingStatus.READY; + private final ProfileStatusReference profilingStatus; // thread dump sequence private int dumpSequence = 0; @@ -52,6 +52,7 @@ public class ThreadProfiler { this.traceSegmentId = traceSegmentId; this.profilingThread = profilingThread; this.executionContext = executionContext; + this.profilingStatus = ProfileStatusReference.createWithPending(); this.profilingMaxTimeMills = TimeUnit.MINUTES.toMillis(Config.Profile.MAX_DURATION); } @@ -62,7 +63,7 @@ public class ThreadProfiler { if (System.currentTimeMillis() - tracingContext.createTime() > executionContext.getTask() .getMinDurationThreshold()) { this.profilingStartTime = System.currentTimeMillis(); - this.profilingStatus = ProfilingStatus.PROFILING; + this.tracingContext.profileStatus().updateStatus(ProfileStatus.PROFILING); } } @@ -70,7 +71,7 @@ public class ThreadProfiler { * Stop profiling status */ public void stopProfiling() { - this.profilingStatus = ProfilingStatus.STOPPED; + this.tracingContext.profileStatus().updateStatus(ProfileStatus.STOPPED); } /** @@ -145,7 +146,7 @@ public class ThreadProfiler { return tracingContext; } - public ProfilingStatus profilingStatus() { + public ProfileStatusReference profilingStatus() { return profilingStatus; } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java index 1de75ec27..d60106794 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java @@ -109,12 +109,7 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround SpanLayer.asHttp(span); if (Config.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) { - final Map parameterMap = request.getParameterMap(); - if (parameterMap != null && !parameterMap.isEmpty()) { - String tagValue = CollectionUtil.toString(parameterMap); - tagValue = Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; - Tags.HTTP.PARAMS.set(span, tagValue); - } + collectHttpParam(request, span); } stackDepth = new StackDepth(); @@ -185,6 +180,11 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround ContextManager.getRuntimeContext().remove(CONTROLLER_METHOD_STACK_DEPTH); } + // Active HTTP parameter collection automatically in the profiling context. + if (!Config.Plugin.SpringMVC.COLLECT_HTTP_PARAMS && span.isProfiling()) { + collectHttpParam(request, span); + } + ContextManager.stopSpan(); } @@ -196,4 +196,13 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround Class[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } + + private void collectHttpParam(HttpServletRequest request, AbstractSpan span) { + final Map parameterMap = request.getParameterMap(); + if (parameterMap != null && !parameterMap.isEmpty()) { + String tagValue = CollectionUtil.toString(parameterMap); + tagValue = Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } } diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java index 3434fdbdf..aa37060c1 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java @@ -83,25 +83,14 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor SpanLayer.asHttp(span); if (Config.Plugin.Tomcat.COLLECT_HTTP_PARAMS) { - final Map parameterMap = new HashMap<>(); - final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest(); - final Parameters parameters = coyoteRequest.getParameters(); - for (final Enumeration names = parameters.getParameterNames(); names.hasMoreElements(); ) { - final String name = names.nextElement(); - parameterMap.put(name, parameters.getParameterValues(name)); - } - - if (!parameterMap.isEmpty()) { - String tagValue = CollectionUtil.toString(parameterMap); - tagValue = Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; - Tags.HTTP.PARAMS.set(span, tagValue); - } + collectHttpParam(request, span); } } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + Request request = (Request) allArguments[0]; HttpServletResponse response = (HttpServletResponse) allArguments[1]; AbstractSpan span = ContextManager.activeSpan(); @@ -109,6 +98,10 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor span.errorOccurred(); Tags.STATUS_CODE.set(span, Integer.toString(response.getStatus())); } + // Active HTTP parameter collection automatically in the profiling context. + if (!Config.Plugin.Tomcat.COLLECT_HTTP_PARAMS && span.isProfiling()) { + collectHttpParam(request, span); + } ContextManager.stopSpan(); ContextManager.getRuntimeContext().remove(Constants.FORWARD_REQUEST_FLAG); return ret; @@ -121,4 +114,20 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor span.log(t); span.errorOccurred(); } + + private void collectHttpParam(Request request, AbstractSpan span) { + final Map parameterMap = new HashMap<>(); + final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest(); + final Parameters parameters = coyoteRequest.getParameters(); + for (final Enumeration names = parameters.getParameterNames(); names.hasMoreElements(); ) { + final String name = names.nextElement(); + parameterMap.put(name, parameters.getParameterValues(name)); + } + + if (!parameterMap.isEmpty()) { + String tagValue = CollectionUtil.toString(parameterMap); + tagValue = Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? StringUtil.cut(tagValue, Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } } diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpan.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpan.java index 3b7d2a2e2..b07e00eaa 100644 --- a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpan.java +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpan.java @@ -22,6 +22,8 @@ import com.google.common.primitives.Ints; import lombok.Data; import lombok.ToString; +import java.util.List; + @Data @ToString public class ProfiledSpan implements Comparable { @@ -31,6 +33,7 @@ public class ProfiledSpan implements Comparable { private String startTime; private String endTime; private String endpointName; + private List tags; @Override public int compareTo(ProfiledSpan o) { diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanMatcher.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanMatcher.java index 71fcf7e2b..82e244e9e 100644 --- a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanMatcher.java +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanMatcher.java @@ -23,6 +23,11 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.apache.skywalking.e2e.verification.AbstractMatcher; +import java.util.Comparator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + @Data @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) @@ -33,6 +38,7 @@ public class ProfiledSpanMatcher extends AbstractMatcher { private String startTime; private String endTime; private String endpointName; + private List tags; @Override public void verify(ProfiledSpan span) { @@ -42,5 +48,14 @@ public class ProfiledSpanMatcher extends AbstractMatcher { doVerify(startTime, span.getStartTime()); doVerify(endTime, span.getEndTime()); doVerify(endpointName, span.getEndpointName()); + + assertThat(tags).hasSameSizeAs(span.getTags()); + + tags.sort(Comparator.comparing(ProfiledSpanTagMatcher::getKey)); + span.getTags().sort(Comparator.comparing(ProfiledSpanTag::getKey)); + + for (int i = 0; i < tags.size(); i++) { + tags.get(i).verify(span.getTags().get(i)); + } } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfilingStatus.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanTag.java similarity index 81% rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfilingStatus.java rename to test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanTag.java index 305b8a868..62042bf1f 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfilingStatus.java +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanTag.java @@ -16,13 +16,14 @@ * */ -package org.apache.skywalking.apm.agent.core.profile; +package org.apache.skywalking.e2e.profile.query; -public enum ProfilingStatus { +import lombok.Data; +import lombok.ToString; - READY, - - PROFILING, - - STOPPED +@Data +@ToString +public class ProfiledSpanTag { + private String key; + private String value; } diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanTagMatcher.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanTagMatcher.java new file mode 100644 index 000000000..ef444369c --- /dev/null +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/profile/query/ProfiledSpanTagMatcher.java @@ -0,0 +1,42 @@ +/* + * 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.e2e.profile.query; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.apache.skywalking.e2e.verification.AbstractMatcher; + +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class ProfiledSpanTagMatcher extends AbstractMatcher { + private String key; + private String value; + + @Override + public void verify(ProfiledSpanTag profiledSpanTag) { + if (value == null) { + value = ""; + } + + doVerify(key, profiledSpanTag.getKey()); + doVerify(value, profiledSpanTag.getValue()); + } +} diff --git a/test/e2e/e2e-data/src/main/resources/profiledSegment.gql b/test/e2e/e2e-data/src/main/resources/profiledSegment.gql index 164fb848a..852c32f10 100644 --- a/test/e2e/e2e-data/src/main/resources/profiledSegment.gql +++ b/test/e2e/e2e-data/src/main/resources/profiledSegment.gql @@ -18,6 +18,9 @@ segment: getProfiledSegment(segmentId: $segmentId) { spans { spanId parentSpanId serviceCode startTime endTime endpointName type peer component isError layer + tags { + key value + } } } }", diff --git a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/profile/ProfileE2E.java b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/profile/ProfileE2E.java index 47fa9a604..c14329368 100644 --- a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/profile/ProfileE2E.java +++ b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/profile/ProfileE2E.java @@ -169,7 +169,7 @@ public class ProfileE2E extends SkyWalkingTestAdapter { final Map user = ImmutableMap.of( "name", "SkyWalking", "enableProfiling", String.valueOf(needProfiling) ); - return restTemplate.postForEntity(instrumentedServiceUrl + "/profile/users", user, String.class); + return restTemplate.postForEntity(instrumentedServiceUrl + "/profile/users?e2e=true", user, String.class); } private void verifyProfiledSegment(String taskId) throws Exception { diff --git a/test/e2e/e2e-test/src/test/resources/expected/profile/profileSegment.yml b/test/e2e/e2e-test/src/test/resources/expected/profile/profileSegment.yml index 4499a5842..f6646e4ea 100644 --- a/test/e2e/e2e-test/src/test/resources/expected/profile/profileSegment.yml +++ b/test/e2e/e2e-test/src/test/resources/expected/profile/profileSegment.yml @@ -20,27 +20,62 @@ spans: startTime: gt 0 endTime: gt 0 endpointName: /profile/users + tags: + - key: url + value: not null + - key: http.method + value: POST + - key: http.params + value: "e2e=[true]" - spanId: 1 parentSpanId: 0 serviceCode: not null startTime: gt 0 endTime: gt 0 endpointName: H2/JDBI/PreparedStatement/executeQuery + tags: + - key: db.type + value: sql + - key: db.instance + value: testdb + - key: db.statement + value: "call next value for hibernate_sequence" - spanId: 2 parentSpanId: 0 serviceCode: not null startTime: gt 0 endTime: gt 0 endpointName: H2/JDBI/PreparedStatement/executeUpdate + tags: + - key: db.type + value: sql + - key: db.instance + value: testdb + - key: db.statement + value: "insert into user (name, id) values (?, ?)" - spanId: 3 parentSpanId: 0 serviceCode: not null startTime: gt 0 endTime: gt 0 endpointName: H2/JDBI/Connection/commit + tags: + - key: db.type + value: sql + - key: db.instance + value: testdb + - key: db.statement + value: - spanId: 4 parentSpanId: 0 serviceCode: not null startTime: gt 0 endTime: gt 0 endpointName: H2/JDBI/Connection/commit + tags: + - key: db.type + value: sql + - key: db.instance + value: testdb + - key: db.statement + value: