This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new e44bc36  provide profiled segment list query (#4322)
e44bc36 is described below

commit e44bc36281cc0c79f263906464c62698bbf5959d
Author: mrproliu <741550...@qq.com>
AuthorDate: Thu Feb 6 21:02:08 2020 +0800

    provide profiled segment list query (#4322)
    
    * provide profiled segment query
    
    Co-authored-by: 吴晟 Wu Sheng <wu.sh...@foxmail.com>
    Co-authored-by: AirTrioa <44222967+airtr...@users.noreply.github.com>
---
 .../core/profile/ProfileTaskExecutionContext.java  |   2 +-
 ...ecord.java => ProfileThreadSnapshotRecord.java} |  14 +--
 .../core/profile/analyze/ProfileAnalyzer.java      |   2 +-
 .../server/core/profile/analyze/ProfileStack.java  |   6 +-
 .../server/core/query/ProfileTaskQueryService.java |  21 +++-
 .../oap/server/core/storage/StorageModule.java     |   3 +-
 .../profile/IProfileThreadSnapshotQueryDAO.java    |  41 ++++++++
 .../oap/query/graphql/resolver/ProfileQuery.java   |   4 +-
 .../handler/ProfileTaskServiceHandler.java         |   4 +-
 .../StorageModuleElasticsearchProvider.java        |   2 +
 .../query/ProfileThreadSnapshotQueryEsDAO.java     | 108 +++++++++++++++++++++
 .../StorageModuleElasticsearch7Provider.java       |   7 +-
 .../storage/plugin/jdbc/h2/H2StorageProvider.java  |   2 +
 .../h2/dao/H2ProfileThreadSnapshotQueryDAO.java    | 101 +++++++++++++++++++
 .../e2e-profile/e2e-profile-test-runner/pom.xml    |   9 +-
 .../src/docker/profile_official_analysis.oal       |  21 ++++
 .../src/docker/rc.d/rc0-prepare.sh                 |   3 +-
 .../skywalking/e2e/profile/ProfileClient.java      |  25 +++++
 .../skywalking/e2e/profile/query/Traces.java       |  35 +++++++
 ...e.ProfileVerificationITCase.profileSegments.yml |  25 +++++
 .../main/resources/getProfileTaskSegmentList.gql   |  26 +++++
 .../skywalking/e2e/ProfileVerificationITCase.java  |  42 +++++++-
 22 files changed, 472 insertions(+), 31 deletions(-)

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 b17414c..16d684c 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
@@ -150,7 +150,7 @@ public class ProfileTaskExecutionContext {
 
     public boolean isStartProfileable() {
         // check is out of max sampling count check
-        return totalStartedProfilingCount.incrementAndGet() > 
task.getMaxSamplingCount();
+        return totalStartedProfilingCount.incrementAndGet() <= 
task.getMaxSamplingCount();
     }
 
     @Override
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskSegmentSnapshotRecord.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileThreadSnapshotRecord.java
similarity index 87%
rename from 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskSegmentSnapshotRecord.java
rename to 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileThreadSnapshotRecord.java
index 36a4cba..981a770 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileTaskSegmentSnapshotRecord.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/ProfileThreadSnapshotRecord.java
@@ -42,9 +42,9 @@ import static 
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.PR
  */
 @Getter
 @Setter
-@ScopeDeclaration(id = PROFILE_TASK_SEGMENT_SNAPSHOT, name = 
"ProfileTaskSegmentSnapshot")
-@Stream(name = ProfileTaskSegmentSnapshotRecord.INDEX_NAME, scopeId = 
PROFILE_TASK_SEGMENT_SNAPSHOT, builder = 
ProfileTaskSegmentSnapshotRecord.Builder.class, processor = 
RecordStreamProcessor.class)
-public class ProfileTaskSegmentSnapshotRecord extends Record {
+@ScopeDeclaration(id = PROFILE_TASK_SEGMENT_SNAPSHOT, name = 
"ProfileThreadSnapshot")
+@Stream(name = ProfileThreadSnapshotRecord.INDEX_NAME, scopeId = 
PROFILE_TASK_SEGMENT_SNAPSHOT, builder = 
ProfileThreadSnapshotRecord.Builder.class, processor = 
RecordStreamProcessor.class)
+public class ProfileThreadSnapshotRecord extends Record {
 
     public static final String INDEX_NAME = "profile_task_segment_snapshot";
     public static final String TASK_ID = "task_id";
@@ -64,11 +64,11 @@ public class ProfileTaskSegmentSnapshotRecord extends 
Record {
         return getTaskId() + Const.ID_SPLIT + getSegmentId() + Const.ID_SPLIT 
+ getSequence() + Const.ID_SPLIT;
     }
 
-    public static class Builder implements 
StorageBuilder<ProfileTaskSegmentSnapshotRecord> {
+    public static class Builder implements 
StorageBuilder<ProfileThreadSnapshotRecord> {
 
         @Override
-        public ProfileTaskSegmentSnapshotRecord map2Data(Map<String, Object> 
dbMap) {
-            final ProfileTaskSegmentSnapshotRecord snapshot = new 
ProfileTaskSegmentSnapshotRecord();
+        public ProfileThreadSnapshotRecord map2Data(Map<String, Object> dbMap) 
{
+            final ProfileThreadSnapshotRecord snapshot = new 
ProfileThreadSnapshotRecord();
             snapshot.setTaskId((String)dbMap.get(TASK_ID));
             snapshot.setSegmentId((String)dbMap.get(SEGMENT_ID));
             snapshot.setDumpTime(((Number)dbMap.get(DUMP_TIME)).longValue());
@@ -83,7 +83,7 @@ public class ProfileTaskSegmentSnapshotRecord extends Record {
         }
 
         @Override
-        public Map<String, Object> data2Map(ProfileTaskSegmentSnapshotRecord 
storageData) {
+        public Map<String, Object> data2Map(ProfileThreadSnapshotRecord 
storageData) {
             final HashMap<String, Object> map = new HashMap<>();
             map.put(TASK_ID, storageData.getTaskId());
             map.put(SEGMENT_ID, storageData.getSegmentId());
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
index df59270..72857f8 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java
@@ -28,7 +28,7 @@ import java.util.stream.Collectors;
 /**
  * Analyze {@link ProfileStack} data to {@link ProfileAnalyzation}
  *
- * See: 
https://github.com/apache/skywalking/blob/docs/en/guides/backend-profile.md#thread-analyst
+ * See: 
https://github.com/apache/skywalking/blob/421ba88dbfba48cdc5845547381aa4763775b4b1/docs/en/guides/backend-profile.md#thread-analyst
  */
 public class ProfileAnalyzer {
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStack.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStack.java
index a3e02b0..c31b609 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStack.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStack.java
@@ -22,12 +22,12 @@ import com.google.common.primitives.Ints;
 import com.google.protobuf.InvalidProtocolBufferException;
 import lombok.Data;
 import org.apache.skywalking.apm.network.language.profile.ThreadStack;
-import 
org.apache.skywalking.oap.server.core.profile.ProfileTaskSegmentSnapshotRecord;
+import 
org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
 
 import java.util.List;
 
 /**
- * Deserialize from {@link ProfileTaskSegmentSnapshotRecord}
+ * Deserialize from {@link ProfileThreadSnapshotRecord}
  */
 @Data
 public class ProfileStack implements Comparable<ProfileStack> {
@@ -36,7 +36,7 @@ public class ProfileStack implements Comparable<ProfileStack> 
{
     private long dumpTime;
     private List<String> stack;
 
-    public static ProfileStack deserialize(ProfileTaskSegmentSnapshotRecord 
record) {
+    public static ProfileStack deserialize(ProfileThreadSnapshotRecord record) 
{
         ThreadStack threadStack = null;
         try {
             threadStack = ThreadStack.parseFrom(record.getStackBinary());
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
index df4ebff..656262c 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java
@@ -21,6 +21,7 @@ import com.google.common.base.Objects;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import 
org.apache.skywalking.oap.server.core.cache.ServiceInstanceInventoryCache;
 import org.apache.skywalking.oap.server.core.cache.ServiceInventoryCache;
+import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
 import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog;
 import org.apache.skywalking.oap.server.core.register.ServiceInstanceInventory;
@@ -28,6 +29,7 @@ import 
org.apache.skywalking.oap.server.core.register.ServiceInventory;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.module.Service;
 import org.apache.skywalking.oap.server.library.util.CollectionUtils;
@@ -48,6 +50,7 @@ public class ProfileTaskQueryService implements Service {
     private final ModuleManager moduleManager;
     private IProfileTaskQueryDAO profileTaskQueryDAO;
     private IProfileTaskLogQueryDAO profileTaskLogQueryDAO;
+    private IProfileThreadSnapshotQueryDAO profileThreadSnapshotQueryDAO;
     private ServiceInventoryCache serviceInventoryCache;
     private ServiceInstanceInventoryCache serviceInstanceInventoryCache;
 
@@ -69,20 +72,27 @@ public class ProfileTaskQueryService implements Service {
         return serviceInventoryCache;
     }
 
-    public IProfileTaskLogQueryDAO getProfileTaskLogQueryDAO() {
+    private IProfileTaskLogQueryDAO getProfileTaskLogQueryDAO() {
         if (isNull(profileTaskLogQueryDAO)) {
             profileTaskLogQueryDAO = 
moduleManager.find(StorageModule.NAME).provider().getService(IProfileTaskLogQueryDAO.class);
         }
         return profileTaskLogQueryDAO;
     }
 
-    public ServiceInstanceInventoryCache getServiceInstanceInventoryCache() {
+    private ServiceInstanceInventoryCache getServiceInstanceInventoryCache() {
         if (isNull(serviceInstanceInventoryCache)) {
             serviceInstanceInventoryCache = 
moduleManager.find(CoreModule.NAME).provider().getService(ServiceInstanceInventoryCache.class);
         }
         return serviceInstanceInventoryCache;
     }
 
+    private IProfileThreadSnapshotQueryDAO getProfileThreadSnapshotQueryDAO() {
+        if (isNull(profileThreadSnapshotQueryDAO)) {
+            profileThreadSnapshotQueryDAO = 
moduleManager.find(StorageModule.NAME).provider().getService(IProfileThreadSnapshotQueryDAO.class);
+        }
+        return profileThreadSnapshotQueryDAO;
+    }
+
     /**
      * search profile task list
      * @param serviceId monitor service
@@ -123,4 +133,11 @@ public class ProfileTaskQueryService implements Service {
         return tasks;
     }
 
+    /**
+     * search profiled traces
+     */
+    public List<BasicTrace> getTaskTraces(String taskId) throws IOException {
+        return 
getProfileThreadSnapshotQueryDAO().queryProfiledSegments(taskId);
+    }
+
 }
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
index 1ae6d54..135976e 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/StorageModule.java
@@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.storage;
 import org.apache.skywalking.oap.server.core.storage.cache.*;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.*;
 import org.apache.skywalking.oap.server.library.module.*;
 
@@ -42,6 +43,6 @@ public class StorageModule extends ModuleDefine {
             IServiceInventoryCacheDAO.class, 
IServiceInstanceInventoryCacheDAO.class,
             IEndpointInventoryCacheDAO.class, 
INetworkAddressInventoryCacheDAO.class,
             ITopologyQueryDAO.class, IMetricsQueryDAO.class, 
ITraceQueryDAO.class, IMetadataQueryDAO.class, IAggregationQueryDAO.class, 
IAlarmQueryDAO.class,
-            ITopNRecordsQueryDAO.class, ILogQueryDAO.class, 
IProfileTaskQueryDAO.class, IProfileTaskLogQueryDAO.class};
+            ITopNRecordsQueryDAO.class, ILogQueryDAO.class, 
IProfileTaskQueryDAO.class, IProfileTaskLogQueryDAO.class, 
IProfileThreadSnapshotQueryDAO.class};
     }
 }
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java
new file mode 100644
index 0000000..99396c8
--- /dev/null
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/profile/IProfileThreadSnapshotQueryDAO.java
@@ -0,0 +1,41 @@
+/*
+ * 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.oap.server.core.storage.profile;
+
+import 
org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
+import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import org.apache.skywalking.oap.server.core.storage.DAO;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * {@link ProfileThreadSnapshotRecord} database queries
+ */
+public interface IProfileThreadSnapshotQueryDAO extends DAO {
+
+    /**
+     * search all profiled segments, need appoint taskId and snapshot sequence 
equals 0
+     * sort by segment start time
+     * @param taskId
+     * @return it represents the segments having profile snapshot data.
+     */
+    List<BasicTrace> queryProfiledSegments(String taskId) throws IOException;
+
+}
diff --git 
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
 
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
index 5c9abb2..350157a 100644
--- 
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
+++ 
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java
@@ -55,8 +55,8 @@ public class ProfileQuery implements GraphQLQueryResolver {
         return getProfileTaskQueryService().getTaskList(serviceId, 
endpointName);
     }
 
-    public List<BasicTrace> getProfileTaskSegmentList(final String taskID) {
-        return Collections.emptyList();
+    public List<BasicTrace> getProfileTaskSegmentList(final String taskID) 
throws IOException {
+        return getProfileTaskQueryService().getTaskTraces(taskID);
     }
 
     public ProfileAnalyzation getProfileAnalyze(final String segmentId, final 
long start, final long end) {
diff --git 
a/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
 
b/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
index b181fd3..6c7e5b8 100644
--- 
a/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
+++ 
b/oap-server/server-receiver-plugin/skywalking-profile-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/profile/provider/handler/ProfileTaskServiceHandler.java
@@ -31,7 +31,7 @@ import 
org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcess
 import org.apache.skywalking.oap.server.core.cache.ProfileTaskCache;
 import org.apache.skywalking.oap.server.core.command.CommandService;
 import org.apache.skywalking.oap.server.core.profile.ProfileTaskLogRecord;
-import 
org.apache.skywalking.oap.server.core.profile.ProfileTaskSegmentSnapshotRecord;
+import 
org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
 import org.apache.skywalking.oap.server.core.query.entity.ProfileTask;
 import 
org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLogOperationType;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
@@ -110,7 +110,7 @@ public class ProfileTaskServiceHandler extends 
ProfileTaskGrpc.ProfileTaskImplBa
                 }
 
                 // build database data
-                final ProfileTaskSegmentSnapshotRecord record = new 
ProfileTaskSegmentSnapshotRecord();
+                final ProfileThreadSnapshotRecord record = new 
ProfileThreadSnapshotRecord();
                 record.setTaskId(snapshot.getTaskId());
                 record.setSegmentId(segmentIdBuilder.toString());
                 record.setDumpTime(snapshot.getTime());
diff --git 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
index e451ac6..c01679f 100644
--- 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
+++ 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/StorageModuleElasticsearchProvider.java
@@ -38,6 +38,7 @@ import 
org.apache.skywalking.oap.server.core.storage.cache.IServiceInstanceInven
 import 
org.apache.skywalking.oap.server.core.storage.cache.IServiceInventoryCacheDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
@@ -121,6 +122,7 @@ public class StorageModuleElasticsearchProvider extends 
ModuleProvider {
 
         this.registerServiceImplementation(IProfileTaskQueryDAO.class, new 
ProfileTaskQueryEsDAO(elasticSearchClient, 
config.getProfileTaskQueryMaxSize()));
         this.registerServiceImplementation(IProfileTaskLogQueryDAO.class, new 
ProfileTaskLogEsDAO(elasticSearchClient, config.getProfileTaskQueryMaxSize()));
+        
this.registerServiceImplementation(IProfileThreadSnapshotQueryDAO.class, new 
ProfileThreadSnapshotQueryEsDAO(elasticSearchClient, 
config.getProfileTaskQueryMaxSize()));
     }
 
     @Override
diff --git 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java
 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java
new file mode 100644
index 0000000..44d7d88
--- /dev/null
+++ 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ProfileThreadSnapshotQueryEsDAO.java
@@ -0,0 +1,108 @@
+/*
+ * 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.oap.server.storage.plugin.elasticsearch.query;
+
+import 
org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import 
org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
+import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
+import 
org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.elasticsearch.search.sort.SortOrder;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ProfileThreadSnapshotQueryEsDAO extends EsDAO implements 
IProfileThreadSnapshotQueryDAO {
+
+    private final int querySegemntMaxSize;
+
+    public ProfileThreadSnapshotQueryEsDAO(ElasticSearchClient client, int 
profileTaskQueryMaxSize) {
+        super(client);
+        this.querySegemntMaxSize = profileTaskQueryMaxSize;
+    }
+
+    @Override
+    public List<BasicTrace> queryProfiledSegments(String taskId) throws 
IOException {
+        // search segment id list
+        SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
+
+        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+        sourceBuilder.query(boolQueryBuilder);
+
+        
boolQueryBuilder.must().add(QueryBuilders.termQuery(ProfileThreadSnapshotRecord.TASK_ID,
 taskId));
+        
boolQueryBuilder.must().add(QueryBuilders.termQuery(ProfileThreadSnapshotRecord.SEQUENCE,
 0));
+
+        sourceBuilder.size(querySegemntMaxSize);
+        sourceBuilder.sort(ProfileThreadSnapshotRecord.DUMP_TIME, 
SortOrder.DESC);
+
+        SearchResponse response = 
getClient().search(ProfileThreadSnapshotRecord.INDEX_NAME, sourceBuilder);
+
+        final LinkedList<String> segments = new LinkedList<>();
+        for (SearchHit searchHit : response.getHits().getHits()) {
+            segments.add((String) 
searchHit.getSourceAsMap().get(ProfileThreadSnapshotRecord.SEGMENT_ID));
+        }
+
+        if (CollectionUtils.isEmpty(segments)) {
+            return Collections.emptyList();
+        }
+
+        // search traces
+        sourceBuilder = SearchSourceBuilder.searchSource();
+
+        boolQueryBuilder = QueryBuilders.boolQuery();
+        sourceBuilder.query(boolQueryBuilder);
+        List<QueryBuilder> shouldQueryList = boolQueryBuilder.should();
+
+        for (String segmentId : segments) {
+            
shouldQueryList.add(QueryBuilders.termQuery(SegmentRecord.SEGMENT_ID, 
segmentId));
+        }
+        sourceBuilder.size(segments.size());
+        sourceBuilder.sort(SegmentRecord.START_TIME, SortOrder.DESC);
+
+        response = getClient().search(SegmentRecord.INDEX_NAME, sourceBuilder);
+
+        List<BasicTrace> result = new ArrayList<>();
+        for (SearchHit searchHit : response.getHits().getHits()) {
+            BasicTrace basicTrace = new BasicTrace();
+
+            
basicTrace.setSegmentId((String)searchHit.getSourceAsMap().get(SegmentRecord.SEGMENT_ID));
+            
basicTrace.setStart(String.valueOf(searchHit.getSourceAsMap().get(SegmentRecord.START_TIME)));
+            
basicTrace.getEndpointNames().add((String)searchHit.getSourceAsMap().get(SegmentRecord.ENDPOINT_NAME));
+            
basicTrace.setDuration(((Number)searchHit.getSourceAsMap().get(SegmentRecord.LATENCY)).intValue());
+            
basicTrace.setError(BooleanUtils.valueToBoolean(((Number)searchHit.getSourceAsMap().get(SegmentRecord.IS_ERROR)).intValue()));
+            
basicTrace.getTraceIds().add((String)searchHit.getSourceAsMap().get(SegmentRecord.TRACE_ID));
+
+            result.add(basicTrace);
+        }
+
+        return result;
+    }
+}
diff --git 
a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
 
b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
index 5fe5775..14bd616 100644
--- 
a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
+++ 
b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/StorageModuleElasticsearch7Provider.java
@@ -33,6 +33,7 @@ import 
org.apache.skywalking.oap.server.core.storage.cache.IServiceInstanceInven
 import 
org.apache.skywalking.oap.server.core.storage.cache.IServiceInventoryCacheDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
@@ -48,10 +49,7 @@ import 
org.apache.skywalking.oap.server.library.module.ModuleStartException;
 import 
org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
 import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.BatchProcessEsDAO;
 import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.HistoryDeleteEsDAO;
-import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ProfileTaskLogEsDAO;
-import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ProfileTaskQueryEsDAO;
-import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopNRecordsQueryEsDAO;
-import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopologyQueryEsDAO;
+import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.*;
 import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch.ttl.ElasticsearchStorageTTL;
 import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.cache.EndpointInventoryCacheEs7DAO;
 import 
org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.cache.NetworkAddressInventoryCacheEs7DAO;
@@ -127,6 +125,7 @@ public class StorageModuleElasticsearch7Provider extends 
ModuleProvider {
 
         this.registerServiceImplementation(IProfileTaskQueryDAO.class, new 
ProfileTaskQueryEsDAO(elasticSearch7Client, 
config.getProfileTaskQueryMaxSize()));
         this.registerServiceImplementation(IProfileTaskLogQueryDAO.class, new 
ProfileTaskLogEsDAO(elasticSearch7Client, config.getProfileTaskQueryMaxSize()));
+        
this.registerServiceImplementation(IProfileThreadSnapshotQueryDAO.class, new 
ProfileThreadSnapshotQueryEsDAO(elasticSearch7Client, 
config.getProfileTaskQueryMaxSize()));
     }
 
     @Override
diff --git 
a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/H2StorageProvider.java
 
b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/H2StorageProvider.java
index 0562648..11783a4 100644
--- 
a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/H2StorageProvider.java
+++ 
b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/H2StorageProvider.java
@@ -24,6 +24,7 @@ import org.apache.skywalking.oap.server.core.storage.*;
 import org.apache.skywalking.oap.server.core.storage.cache.*;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskLogQueryDAO;
 import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDAO;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.*;
 import org.apache.skywalking.oap.server.core.storage.ttl.GeneralStorageTTL;
 import 
org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
@@ -94,6 +95,7 @@ public class H2StorageProvider extends ModuleProvider {
 
         this.registerServiceImplementation(IProfileTaskQueryDAO.class, new 
H2ProfileTaskQueryDAO(h2Client));
         this.registerServiceImplementation(IProfileTaskLogQueryDAO.class, new 
H2ProfileTaskLogQueryDAO(h2Client));
+        
this.registerServiceImplementation(IProfileThreadSnapshotQueryDAO.class, new 
H2ProfileThreadSnapshotQueryDAO(h2Client));
     }
 
     @Override public void start() throws ServiceNotProvidedException, 
ModuleStartException {
diff --git 
a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileThreadSnapshotQueryDAO.java
 
b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileThreadSnapshotQueryDAO.java
new file mode 100644
index 0000000..439a2e2
--- /dev/null
+++ 
b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2ProfileThreadSnapshotQueryDAO.java
@@ -0,0 +1,101 @@
+/*
+ * 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.oap.server.storage.plugin.jdbc.h2.dao;
+
+import 
org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import 
org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord;
+import org.apache.skywalking.oap.server.core.query.entity.BasicTrace;
+import 
org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
+import 
org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
+import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+import org.elasticsearch.search.sort.SortOrder;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public class H2ProfileThreadSnapshotQueryDAO implements 
IProfileThreadSnapshotQueryDAO {
+    private JDBCHikariCPClient h2Client;
+
+    public H2ProfileThreadSnapshotQueryDAO(JDBCHikariCPClient h2Client) {
+        this.h2Client = h2Client;
+    }
+
+    @Override
+    public List<BasicTrace> queryProfiledSegments(String taskId) throws 
IOException {
+        // search segment id list
+        StringBuilder sql = new StringBuilder();
+        sql.append("select 
").append(ProfileThreadSnapshotRecord.SEGMENT_ID).append(" from 
").append(ProfileThreadSnapshotRecord.INDEX_NAME);
+
+        sql.append(" where 
").append(ProfileThreadSnapshotRecord.TASK_ID).append(" = ? and 
").append(ProfileThreadSnapshotRecord.SEQUENCE).append(" = 0");
+
+        final LinkedList<String> segments = new LinkedList<>();
+        try (Connection connection = h2Client.getConnection()) {
+            try (ResultSet resultSet = h2Client.executeQuery(connection, 
sql.toString(), taskId)) {
+                while (resultSet.next()) {
+                    
segments.add(resultSet.getString(ProfileThreadSnapshotRecord.SEGMENT_ID));
+                }
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+
+        if (CollectionUtils.isEmpty(segments)) {
+            return Collections.emptyList();
+        }
+
+        // search traces
+        sql = new StringBuilder();
+        sql.append("select * from ").append(SegmentRecord.INDEX_NAME).append(" 
where ");
+        sql.append(" 1=1 ");
+        for (int i = 0; i < segments.size(); i++) {
+            sql.append(" and ").append(SegmentRecord.SEGMENT_ID).append(" = ? 
");
+        }
+        sql.append(" order by ").append(SegmentRecord.START_TIME).append(" 
").append(SortOrder.DESC);
+
+        ArrayList<BasicTrace> result = new ArrayList<>(segments.size());
+        try (Connection connection = h2Client.getConnection()) {
+
+            try (ResultSet resultSet = h2Client.executeQuery(connection, 
sql.toString(), segments.toArray(new String[segments.size()]))) {
+                while (resultSet.next()) {
+                    BasicTrace basicTrace = new BasicTrace();
+
+                    
basicTrace.setSegmentId(resultSet.getString(SegmentRecord.SEGMENT_ID));
+                    
basicTrace.setStart(resultSet.getString(SegmentRecord.START_TIME));
+                    
basicTrace.getEndpointNames().add(resultSet.getString(SegmentRecord.ENDPOINT_NAME));
+                    
basicTrace.setDuration(resultSet.getInt(SegmentRecord.LATENCY));
+                    
basicTrace.setError(BooleanUtils.valueToBoolean(resultSet.getInt(SegmentRecord.IS_ERROR)));
+                    String traceIds = 
resultSet.getString(SegmentRecord.TRACE_ID);
+                    basicTrace.getTraceIds().add(traceIds);
+
+                    result.add(basicTrace);
+                }
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+        return result;
+    }
+}
diff --git a/test/e2e/e2e-profile/e2e-profile-test-runner/pom.xml 
b/test/e2e/e2e-profile/e2e-profile-test-runner/pom.xml
index 203813a..e3cfb07 100644
--- a/test/e2e/e2e-profile/e2e-profile-test-runner/pom.xml
+++ b/test/e2e/e2e-profile/e2e-profile-test-runner/pom.xml
@@ -115,7 +115,8 @@
                                                 
<volume>${project.build.directory}:/home</volume>
                                                 
<volume>../${provider.name}/target/${provider.name}-${project.version}.jar:/home/${provider.name}-${project.version}.jar</volume>
                                                 
<volume>${project.basedir}/src/docker/rc.d:/rc.d:ro</volume>
-                                                
<volume>${project.basedir}/src/docker/clusterize.awk:/clusterize.awk</volume>
+                                                
<volume>${project.basedir}/src/docker/adapt_storage.awk:/adapt_storage.awk</volume>
+                                                
<volume>${project.basedir}/src/docker/profile_official_analysis.oal:/profile_official_analysis.oal</volume>
                                             </bind>
                                         </volumes>
                                         <wait>
@@ -168,7 +169,8 @@
                                                 <volume>${sw.home}:/sw</volume>
                                                 
<volume>../${provider.name}/target/${provider.name}-${project.version}.jar:/home/${provider.name}-${project.version}.jar</volume>
                                                 
<volume>${project.basedir}/src/docker/rc.d:/rc.d:ro</volume>
-                                                
<volume>${project.basedir}/src/docker/clusterize.awk:/clusterize.awk</volume>
+                                                
<volume>${project.basedir}/src/docker/adapt_storage.awk:/adapt_storage.awk</volume>
+                                                
<volume>${project.basedir}/src/docker/profile_official_analysis.oal:/profile_official_analysis.oal</volume>
                                             </bind>
                                         </volumes>
                                         <wait>
@@ -251,7 +253,8 @@
                                                 <volume>${sw.home}:/sw</volume>
                                                 
<volume>../${provider.name}/target/${provider.name}-${project.version}.jar:/home/${provider.name}-${project.version}.jar</volume>
                                                 
<volume>${project.basedir}/src/docker/rc.d:/rc.d:ro</volume>
-                                                
<volume>${project.basedir}/src/docker/clusterize.awk:/clusterize.awk</volume>
+                                                
<volume>${project.basedir}/src/docker/adapt_storage.awk:/adapt_storage.awk</volume>
+                                                
<volume>${project.basedir}/src/docker/profile_official_analysis.oal:/profile_official_analysis.oal</volume>
                                             </bind>
                                         </volumes>
                                         <wait>
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/profile_official_analysis.oal
 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/profile_official_analysis.oal
new file mode 100755
index 0000000..cc6894b
--- /dev/null
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/profile_official_analysis.oal
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ *
+ */
+
+
+// Disable all oal in profile e2e testing.
+
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/rc.d/rc0-prepare.sh 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/rc.d/rc0-prepare.sh
index 4693ad0..9b18d3e 100755
--- 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/rc.d/rc0-prepare.sh
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/docker/rc.d/rc0-prepare.sh
@@ -33,6 +33,7 @@ fi
 # substitute application.yml to adapt the storage
 cd ${SW_HOME}/config \
     && gawk -f /adapt_storage.awk application.yml > clusterized_app.yml \
-    && mv clusterized_app.yml application.yml
+    && mv clusterized_app.yml application.yml \
+    && cp /profile_official_analysis.oal official_analysis.oal \
 
 cd ${original_wd}
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/ProfileClient.java
 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/ProfileClient.java
index d01c0a3..16bfc9b 100644
--- 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/ProfileClient.java
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/ProfileClient.java
@@ -26,6 +26,8 @@ import 
org.apache.skywalking.e2e.profile.creation.ProfileTaskCreationResult;
 import 
org.apache.skywalking.e2e.profile.creation.ProfileTaskCreationResultWrapper;
 import org.apache.skywalking.e2e.profile.query.ProfileTaskQuery;
 import org.apache.skywalking.e2e.profile.query.ProfileTasks;
+import org.apache.skywalking.e2e.profile.query.Traces;
+import org.apache.skywalking.e2e.trace.Trace;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
@@ -36,6 +38,8 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URL;
 import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -95,5 +99,26 @@ public class ProfileClient extends SimpleQueryClient {
         return responseEntity.getBody().getData();
     }
 
+    public List<Trace> getProfiledTraces(final String taskId) throws Exception 
{
+        final URL queryFileUrl = 
Resources.getResource("getProfileTaskSegmentList.gql");
+        final String queryString = Resources.readLines(queryFileUrl, 
Charset.forName("UTF8"))
+                .stream()
+                .filter(it -> !it.startsWith("#"))
+                .collect(Collectors.joining())
+                .replace("{taskID}", taskId);
+        final ResponseEntity<GQLResponse<Traces>> responseEntity = 
restTemplate.exchange(
+                new RequestEntity<>(queryString, HttpMethod.POST, 
URI.create(endpointUrl)),
+                new ParameterizedTypeReference<GQLResponse<Traces>>() {
+                }
+        );
+
+        if (responseEntity.getStatusCode() != HttpStatus.OK) {
+            throw new RuntimeException("Response status != 200, actual: " + 
responseEntity.getStatusCode());
+        }
+
+        return 
Objects.requireNonNull(responseEntity.getBody()).getData().getTraces();
+    }
+
+
 
 }
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/query/Traces.java
 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/query/Traces.java
new file mode 100644
index 0000000..118131a
--- /dev/null
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/java/org/apache/skywalking/e2e/profile/query/Traces.java
@@ -0,0 +1,35 @@
+/*
+ * 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.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.apache.skywalking.e2e.trace.Trace;
+
+import java.util.List;
+
+@Setter
+@Getter
+@ToString
+public class Traces {
+
+    private List<Trace> traces;
+
+}
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/expected-data/org.apache.skywalking.e2e.ProfileVerificationITCase.profileSegments.yml
 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/expected-data/org.apache.skywalking.e2e.ProfileVerificationITCase.profileSegments.yml
new file mode 100644
index 0000000..4542e5d
--- /dev/null
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/expected-data/org.apache.skywalking.e2e.ProfileVerificationITCase.profileSegments.yml
@@ -0,0 +1,25 @@
+# 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.
+
+traces:
+  - key: not null
+    endpointNames:
+      - /e2e/users
+    duration: ge 0
+    start: gt 0
+    isError: false
+    traceIds:
+      - not null
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileTaskSegmentList.gql
 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileTaskSegmentList.gql
new file mode 100644
index 0000000..560d844
--- /dev/null
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileTaskSegmentList.gql
@@ -0,0 +1,26 @@
+# 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.
+
+{
+  "query":"query getProfileTaskSegmentList($taskID: String!) {
+    traces: getProfileTaskSegmentList(taskID: $taskID) {
+        key: segmentId endpointNames duration start isError traceIds
+    }
+  }",
+  "variables": {
+    "taskID": "{taskID}"
+  }
+}
\ No newline at end of file
diff --git 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/test/java/org/apache/skywalking/e2e/ProfileVerificationITCase.java
 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/test/java/org/apache/skywalking/e2e/ProfileVerificationITCase.java
index 2289ae8..25b05df 100644
--- 
a/test/e2e/e2e-profile/e2e-profile-test-runner/src/test/java/org/apache/skywalking/e2e/ProfileVerificationITCase.java
+++ 
b/test/e2e/e2e-profile/e2e-profile-test-runner/src/test/java/org/apache/skywalking/e2e/ProfileVerificationITCase.java
@@ -35,6 +35,7 @@ import org.apache.skywalking.e2e.service.instance.Instances;
 import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
 import org.apache.skywalking.e2e.service.instance.InstancesQuery;
 import org.apache.skywalking.e2e.trace.Trace;
+import org.apache.skywalking.e2e.trace.TracesMatcher;
 import org.apache.skywalking.e2e.trace.TracesQuery;
 import org.junit.Before;
 import org.junit.Test;
@@ -75,11 +76,9 @@ public class ProfileVerificationITCase {
     @Before
     public void setUp() {
         final String swWebappHost = System.getProperty("sw.webapp.host", 
"127.0.0.1");
-        //        final String swWebappPort = 
System.getProperty("sw.webapp.port", "32783");
         final String swWebappPort = System.getProperty("sw.webapp.port", 
"12800");
         final String instrumentedServiceHost = 
System.getProperty("service.host", "127.0.0.1");
-        final String instrumentedServicePort = 
System.getProperty("service.port", "32782");
-        //        final String instrumentedServicePort = 
System.getProperty("service.port", "9090");
+        final String instrumentedServicePort = 
System.getProperty("service.port", "9090");
         profileClient = new ProfileClient(swWebappHost, swWebappPort);
         instrumentedServiceUrl = "http://"; + instrumentedServiceHost + ":" + 
instrumentedServicePort;
     }
@@ -109,7 +108,16 @@ public class ProfileVerificationITCase {
         }
 
         // verify basic info
-        verifyServices(minutesAgo);
+        int verifyServiceCount = 3;
+        for (int i = 1; i <= verifyServiceCount; i++) {
+            try {
+                verifyServices(minutesAgo);
+            } catch (Exception e) {
+                if (i == verifyServiceCount) {
+                    throw new IllegalStateException("match services fail!", e);
+                }
+            }
+        }
 
         // create profile task
         verifyCreateProfileTask(minutesAgo);
@@ -159,6 +167,32 @@ public class ProfileVerificationITCase {
 
         // verify task execution finish
         verifyProfileTask(creationRequest.getServiceId(), 
"expected-data/org.apache.skywalking.e2e.ProfileVerificationITCase.profileTasks.finished.yml");
+
+        // verify profiled segment
+        verifyProfiledSegment(creationResult.getId());
+    }
+
+    private void verifyProfiledSegment(String taskId) throws 
InterruptedException {
+        // found segment id
+        String foundedSegmentId = null;
+        for (int i = 0; i < 10; i++) {
+            try {
+                List<Trace> traces = profileClient.getProfiledTraces(taskId);
+                LOGGER.info("get profiled segemnt list: {}", traces);
+
+                InputStream expectedInputStream = new 
ClassPathResource("expected-data/org.apache.skywalking.e2e.ProfileVerificationITCase.profileSegments.yml").getInputStream();
+                final TracesMatcher tracesMatcher = new 
Yaml().loadAs(expectedInputStream, TracesMatcher.class);
+                tracesMatcher.verifyLoosely(traces);
+                foundedSegmentId = traces.get(0).getKey();
+                break;
+
+            } catch (Exception e) {
+                if (i == 10 - 1) {
+                    throw new IllegalStateException("match profiled segment 
list fail!", e);
+                }
+                TimeUnit.SECONDS.sleep(retryInterval);
+            }
+        }
     }
 
     private void verifyProfileTask(int serviceId, String verifyResources) 
throws InterruptedException {

Reply via email to