Provide HTTP parameter in the profiling contet (#4546)
* Provide active HTTP parameter collection automatically in the profiling context * Fix style check * fix style error * Add profile status, storage it into TracingContext. simplify to get profiling method * Change the profile status field name in TracingContext * Replace gone images * resolve issues * resole description issues Co-authored-by: Mrproliu <mrproliu@lagou.com> Co-authored-by: kezhenxu94 <kezhenxu94@163.com>
This commit is contained in:
parent
a9d34e3b61
commit
ace781ff49
|
|
@ -224,4 +224,5 @@ public class ContextManager implements BootService {
|
|||
|
||||
return runtimeContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,4 +358,9 @@ public abstract class AbstractTracingSpan implements AbstractSpan {
|
|||
isAsyncStopped = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProfiling() {
|
||||
return this.owner.profileStatus().isProfiling();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,11 @@ public class NoopSpan implements AbstractSpan {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProfiling() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractSpan prepareForAsync() {
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,12 +109,7 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround
|
|||
SpanLayer.asHttp(span);
|
||||
|
||||
if (Config.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
|
||||
final Map<String, String[]> 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<String, String[]> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,25 +83,14 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor
|
|||
SpanLayer.asHttp(span);
|
||||
|
||||
if (Config.Plugin.Tomcat.COLLECT_HTTP_PARAMS) {
|
||||
final Map<String, String[]> parameterMap = new HashMap<>();
|
||||
final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest();
|
||||
final Parameters parameters = coyoteRequest.getParameters();
|
||||
for (final Enumeration<String> 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<String, String[]> parameterMap = new HashMap<>();
|
||||
final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest();
|
||||
final Parameters parameters = coyoteRequest.getParameters();
|
||||
for (final Enumeration<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ProfiledSpan> {
|
||||
|
|
@ -31,6 +33,7 @@ public class ProfiledSpan implements Comparable<ProfiledSpan> {
|
|||
private String startTime;
|
||||
private String endTime;
|
||||
private String endpointName;
|
||||
private List<ProfiledSpanTag> tags;
|
||||
|
||||
@Override
|
||||
public int compareTo(ProfiledSpan o) {
|
||||
|
|
|
|||
|
|
@ -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<ProfiledSpan> {
|
|||
private String startTime;
|
||||
private String endTime;
|
||||
private String endpointName;
|
||||
private List<ProfiledSpanTagMatcher> tags;
|
||||
|
||||
@Override
|
||||
public void verify(ProfiledSpan span) {
|
||||
|
|
@ -42,5 +48,14 @@ public class ProfiledSpanMatcher extends AbstractMatcher<ProfiledSpan> {
|
|||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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<ProfiledSpanTag> {
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
@Override
|
||||
public void verify(ProfiledSpanTag profiledSpanTag) {
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
doVerify(key, profiledSpanTag.getKey());
|
||||
doVerify(value, profiledSpanTag.getValue());
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,9 @@
|
|||
segment: getProfiledSegment(segmentId: $segmentId) {
|
||||
spans {
|
||||
spanId parentSpanId serviceCode startTime endTime endpointName type peer component isError layer
|
||||
tags {
|
||||
key value
|
||||
}
|
||||
}
|
||||
}
|
||||
}",
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ public class ProfileE2E extends SkyWalkingTestAdapter {
|
|||
final Map<String, String> 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 {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue