You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2022/10/22 03:31:01 UTC

[skywalking] branch master updated: Support new records query protocol (#9827)

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 2e6e3faef0 Support new records query protocol (#9827)
2e6e3faef0 is described below

commit 2e6e3faef0b4f61442bf512f8e68620964a5ffbb
Author: mrproliu <74...@qq.com>
AuthorDate: Sat Oct 22 11:30:52 2022 +0800

    Support new records query protocol (#9827)
---
 docs/en/changes/changes.md                         |  2 +
 .../analyzer/dsl/registry/ProcessRegistry.java     |  2 +-
 .../skywalking/oap/server/core/CoreModule.java     |  2 +
 .../oap/server/core/CoreModuleProvider.java        |  2 +
 .../manual/cache/CacheSlowAccessDispatcher.java    |  4 +-
 .../manual/cache/TopNCacheReadCommand.java         |  8 +--
 .../manual/cache/TopNCacheWriteCommand.java        |  8 +--
 .../database/DatabaseStatementDispatcher.java      |  2 +-
 .../manual/database/TopNDatabaseStatement.java     |  8 +--
 .../oap/server/core/analysis/topn/TopN.java        |  6 +--
 ...dsQueryService.java => RecordQueryService.java} | 35 ++++++------
 .../server/core/query/TopNRecordsQueryService.java | 24 +++++----
 .../server/core/query/input/RecordCondition.java   | 62 ++++++++++++++++++++++
 .../oap/server/core/query/type/Record.java         | 53 ++++++++++++++++++
 .../oap/server/core/storage/StorageModule.java     |  4 +-
 ...NRecordsQueryDAO.java => IRecordsQueryDAO.java} | 12 ++---
 .../skywalking/oap/server/core/CoreModuleTest.java |  2 +-
 .../oap/query/graphql/GraphQLQueryProvider.java    |  5 +-
 .../oap/query/graphql/resolver/MetricsQuery.java   | 25 ++++++---
 .../oap/query/graphql/resolver/RecordsQuery.java   | 52 ++++++++++++++++++
 .../src/main/resources/query-protocol              |  2 +-
 ...sQueryDAO.java => BanyanDBRecordsQueryDAO.java} | 31 +++++------
 .../plugin/banyandb/BanyanDBStorageProvider.java   |  4 +-
 .../StorageModuleElasticsearchProvider.java        |  6 +--
 ...cordsQueryEsDAO.java => RecordsQueryEsDAO.java} | 33 ++++++------
 .../storage/plugin/jdbc/h2/H2StorageProvider.java  |  6 +--
 ...RecordsQueryDAO.java => H2RecordsQueryDAO.java} | 36 +++++++------
 .../plugin/jdbc/mysql/MySQLStorageProvider.java    |  6 +--
 .../jdbc/postgresql/PostgreSQLStorageProvider.java |  6 +--
 .../mysql/MySQLShardingStorageProvider.java        |  6 +--
 .../plugin/jdbc/tidb/TiDBStorageProvider.java      |  6 +--
 .../e2e-v2/cases/browser/expected/trace-detail.yml |  2 +
 .../cases/go/expected/trace-correlation-detail.yml |  5 ++
 .../cases/meter/expected/record-has-value.yml      |  4 +-
 test/e2e-v2/cases/meter/meter-cases.yaml           |  2 +-
 test/e2e-v2/cases/mysql/expected/db-has-value.yml  |  8 ++-
 test/e2e-v2/cases/mysql/mysql-cases.yaml           |  2 +-
 .../cases/php/expected/trace-info-detail.yml       |  3 ++
 .../cases/postgresql/expected/db-has-value.yml     |  8 ++-
 test/e2e-v2/cases/postgresql/postgresql-cases.yaml |  2 +-
 .../cases/python/expected/trace-test-detail.yml    |  7 +++
 .../expected/trace-info-detail.yml                 |  1 +
 .../expected/trace-users-detail.yml                |  1 +
 .../cases/simple/expected/trace-users-detail.yml   |  3 ++
 .../cases/storage/expected/trace-users-detail.yml  |  3 ++
 test/e2e-v2/script/env                             |  2 +-
 46 files changed, 370 insertions(+), 143 deletions(-)

diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index e4d32e0aec..b7b1515e16 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -65,6 +65,8 @@
 * Support `sumPerMinLabeled` in `MAL`.
 * Bump up jackson databind, snakeyaml, grpc dependencies.
 * Support export `Trace` and `Log` through Kafka.
+* [**Breaking Change**] Support new records query protocol, rename the column named `service_id` to `entity_id` for support difference entity.
+  Please re-create `top_n_database_statement` index/table.
 
 #### UI
 
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/registry/ProcessRegistry.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/registry/ProcessRegistry.java
index cbf2da8646..992e17621b 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/registry/ProcessRegistry.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/registry/ProcessRegistry.java
@@ -66,7 +66,7 @@ public class ProcessRegistry {
         return generateVirtualProcess(service, instance, name);
     }
 
-    private static String generateVirtualProcess(String service, String instance, String processName) {
+    public static String generateVirtualProcess(String service, String instance, String processName) {
         final ProcessTraffic traffic = new ProcessTraffic();
         final String serviceId = IDManager.ServiceID.buildId(service, true);
         traffic.setServiceId(serviceId);
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
index bdd6e1367a..5c67c10a53 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModule.java
@@ -42,6 +42,7 @@ import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
 import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
 import org.apache.skywalking.oap.server.core.query.MetricsQueryService;
 import org.apache.skywalking.oap.server.core.profiling.trace.ProfileTaskQueryService;
+import org.apache.skywalking.oap.server.core.query.RecordQueryService;
 import org.apache.skywalking.oap.server.core.query.TagAutoCompleteQueryService;
 import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
 import org.apache.skywalking.oap.server.core.query.TopologyQueryService;
@@ -128,6 +129,7 @@ public class CoreModule extends ModuleDefine {
         classes.add(BrowserLogQueryService.class);
         classes.add(EventQueryService.class);
         classes.add(TagAutoCompleteQueryService.class);
+        classes.add(RecordQueryService.class);
     }
 
     private void addServerInterface(List<Class> classes) {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
index 8ed6c14ece..498ff27136 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
@@ -64,6 +64,7 @@ import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
 import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
 import org.apache.skywalking.oap.server.core.query.MetricsQueryService;
 import org.apache.skywalking.oap.server.core.profiling.trace.ProfileTaskQueryService;
+import org.apache.skywalking.oap.server.core.query.RecordQueryService;
 import org.apache.skywalking.oap.server.core.query.TagAutoCompleteQueryService;
 import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
 import org.apache.skywalking.oap.server.core.query.TopologyQueryService;
@@ -265,6 +266,7 @@ public class CoreModuleProvider extends ModuleProvider {
         this.registerServiceImplementation(TopNRecordsQueryService.class, new TopNRecordsQueryService(getManager()));
         this.registerServiceImplementation(EventQueryService.class, new EventQueryService(getManager()));
         this.registerServiceImplementation(TagAutoCompleteQueryService.class, new TagAutoCompleteQueryService(getManager(), moduleConfig));
+        this.registerServiceImplementation(RecordQueryService.class, new RecordQueryService(getManager()));
 
         // add profile service implementations
         this.registerServiceImplementation(
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/CacheSlowAccessDispatcher.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/CacheSlowAccessDispatcher.java
index 8d9520925b..f72b6da884 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/CacheSlowAccessDispatcher.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/CacheSlowAccessDispatcher.java
@@ -34,7 +34,7 @@ public class CacheSlowAccessDispatcher implements SourceDispatcher<CacheSlowAcce
             readCommand.setCommand(source.getCommand() + " " + source.getKey());
             readCommand.setLatency(source.getLatency());
             readCommand.setTraceId(source.getTraceId());
-            readCommand.setServiceId(source.getCacheServiceId());
+            readCommand.setEntityId(source.getCacheServiceId());
             readCommand.setTimeBucket(source.getTimeBucket());
             TopNStreamProcessor.getInstance().in(readCommand);
         } else if (source.getOperation() == VirtualCacheOperation.Write) {
@@ -43,7 +43,7 @@ public class CacheSlowAccessDispatcher implements SourceDispatcher<CacheSlowAcce
             writeCommand.setCommand(source.getCommand() + " " + source.getKey());
             writeCommand.setLatency(source.getLatency());
             writeCommand.setTraceId(source.getTraceId());
-            writeCommand.setServiceId(source.getCacheServiceId());
+            writeCommand.setEntityId(source.getCacheServiceId());
             writeCommand.setTimeBucket(source.getTimeBucket());
             TopNStreamProcessor.getInstance().in(writeCommand);
         }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheReadCommand.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheReadCommand.java
index 42ecf57ccc..26d01aab99 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheReadCommand.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheReadCommand.java
@@ -56,12 +56,12 @@ public class TopNCacheReadCommand extends TopN {
         if (o == null || getClass() != o.getClass())
             return false;
         TopNCacheReadCommand statement = (TopNCacheReadCommand) o;
-        return Objects.equals(getServiceId(), statement.getServiceId());
+        return Objects.equals(getEntityId(), statement.getEntityId());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(getServiceId());
+        return Objects.hash(getEntityId());
     }
 
     public static class Builder implements StorageBuilder<TopNCacheReadCommand> {
@@ -71,7 +71,7 @@ public class TopNCacheReadCommand extends TopN {
             statement.setCommand((String) converter.get(STATEMENT));
             statement.setTraceId((String) converter.get(TRACE_ID));
             statement.setLatency(((Number) converter.get(LATENCY)).longValue());
-            statement.setServiceId((String) converter.get(SERVICE_ID));
+            statement.setEntityId((String) converter.get(ENTITY_ID));
             statement.setTimeBucket(((Number) converter.get(TIME_BUCKET)).longValue());
             return statement;
         }
@@ -81,7 +81,7 @@ public class TopNCacheReadCommand extends TopN {
             converter.accept(STATEMENT, storageData.getCommand());
             converter.accept(TRACE_ID, storageData.getTraceId());
             converter.accept(LATENCY, storageData.getLatency());
-            converter.accept(SERVICE_ID, storageData.getServiceId());
+            converter.accept(ENTITY_ID, storageData.getEntityId());
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
         }
     }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheWriteCommand.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheWriteCommand.java
index 7e06ecd3a2..ca35032eb8 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheWriteCommand.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/cache/TopNCacheWriteCommand.java
@@ -57,12 +57,12 @@ public class TopNCacheWriteCommand extends TopN {
         if (o == null || getClass() != o.getClass())
             return false;
         TopNCacheWriteCommand statement = (TopNCacheWriteCommand) o;
-        return Objects.equals(getServiceId(), statement.getServiceId());
+        return Objects.equals(getEntityId(), statement.getEntityId());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(getServiceId());
+        return Objects.hash(getEntityId());
     }
 
     public static class Builder implements StorageBuilder<TopNCacheWriteCommand> {
@@ -72,7 +72,7 @@ public class TopNCacheWriteCommand extends TopN {
             statement.setCommand((String) converter.get(STATEMENT));
             statement.setTraceId((String) converter.get(TRACE_ID));
             statement.setLatency(((Number) converter.get(LATENCY)).longValue());
-            statement.setServiceId((String) converter.get(SERVICE_ID));
+            statement.setEntityId((String) converter.get(ENTITY_ID));
             statement.setTimeBucket(((Number) converter.get(TIME_BUCKET)).longValue());
             return statement;
         }
@@ -82,7 +82,7 @@ public class TopNCacheWriteCommand extends TopN {
             converter.accept(STATEMENT, storageData.getCommand());
             converter.accept(TRACE_ID, storageData.getTraceId());
             converter.accept(LATENCY, storageData.getLatency());
-            converter.accept(SERVICE_ID, storageData.getServiceId());
+            converter.accept(ENTITY_ID, storageData.getEntityId());
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
         }
     }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/DatabaseStatementDispatcher.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/DatabaseStatementDispatcher.java
index 1f810b2774..2af4820334 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/DatabaseStatementDispatcher.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/DatabaseStatementDispatcher.java
@@ -28,7 +28,7 @@ public class DatabaseStatementDispatcher implements SourceDispatcher<DatabaseSlo
     public void dispatch(DatabaseSlowStatement source) {
         TopNDatabaseStatement statement = new TopNDatabaseStatement();
         statement.setId(source.getId());
-        statement.setServiceId(source.getDatabaseServiceId());
+        statement.setEntityId(source.getDatabaseServiceId());
         statement.setLatency(source.getLatency());
         statement.setStatement(source.getStatement());
         statement.setTimeBucket(source.getTimeBucket());
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/TopNDatabaseStatement.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/TopNDatabaseStatement.java
index 1b0fe89f2e..284c25c6b4 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/TopNDatabaseStatement.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/database/TopNDatabaseStatement.java
@@ -56,12 +56,12 @@ public class TopNDatabaseStatement extends TopN {
         if (o == null || getClass() != o.getClass())
             return false;
         TopNDatabaseStatement statement = (TopNDatabaseStatement) o;
-        return Objects.equals(getServiceId(), statement.getServiceId());
+        return Objects.equals(getEntityId(), statement.getEntityId());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(getServiceId());
+        return Objects.hash(getEntityId());
     }
 
     public static class Builder implements StorageBuilder<TopNDatabaseStatement> {
@@ -71,7 +71,7 @@ public class TopNDatabaseStatement extends TopN {
             statement.setStatement((String) converter.get(STATEMENT));
             statement.setTraceId((String) converter.get(TRACE_ID));
             statement.setLatency(((Number) converter.get(LATENCY)).longValue());
-            statement.setServiceId((String) converter.get(SERVICE_ID));
+            statement.setEntityId((String) converter.get(ENTITY_ID));
             statement.setTimeBucket(((Number) converter.get(TIME_BUCKET)).longValue());
             return statement;
         }
@@ -81,7 +81,7 @@ public class TopNDatabaseStatement extends TopN {
             converter.accept(STATEMENT, storageData.getStatement());
             converter.accept(TRACE_ID, storageData.getTraceId());
             converter.accept(LATENCY, storageData.getLatency());
-            converter.accept(SERVICE_ID, storageData.getServiceId());
+            converter.accept(ENTITY_ID, storageData.getEntityId());
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
         }
     }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/topn/TopN.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/topn/TopN.java
index 27c2f43df9..5711951b5c 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/topn/TopN.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/topn/TopN.java
@@ -32,7 +32,7 @@ public abstract class TopN extends Record implements ComparableStorageData {
     public static final String STATEMENT = "statement";
     public static final String LATENCY = "latency";
     public static final String TRACE_ID = "trace_id";
-    public static final String SERVICE_ID = "service_id";
+    public static final String ENTITY_ID = "entity_id";
     
     @Getter
     @Setter
@@ -44,9 +44,9 @@ public abstract class TopN extends Record implements ComparableStorageData {
     private String traceId;
     @Getter
     @Setter
-    @Column(columnName = SERVICE_ID)
+    @Column(columnName = ENTITY_ID)
     @BanyanDB.ShardingKey(index = 0)
-    private String serviceId;
+    private String entityId;
 
     @Override
     public int compareTo(Object o) {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java
similarity index 60%
copy from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
copy to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java
index 31c55d56a6..ed8bf65e85 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/RecordQueryService.java
@@ -18,36 +18,37 @@
 
 package org.apache.skywalking.oap.server.core.query;
 
-import java.io.IOException;
-import java.util.List;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
-import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
-import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.module.Service;
 
-public class TopNRecordsQueryService implements Service {
+import java.io.IOException;
+import java.util.List;
+
+public class RecordQueryService implements Service {
     private final ModuleManager moduleManager;
-    private ITopNRecordsQueryDAO topNRecordsQueryDAO;
+    private IRecordsQueryDAO recordsQueryDAO;
 
-    public TopNRecordsQueryService(ModuleManager manager) {
+    public RecordQueryService(ModuleManager manager) {
         this.moduleManager = manager;
     }
 
-    private ITopNRecordsQueryDAO getTopNRecordsQueryDAO() {
-        if (topNRecordsQueryDAO == null) {
-            this.topNRecordsQueryDAO = moduleManager.find(StorageModule.NAME)
-                                                    .provider()
-                                                    .getService(ITopNRecordsQueryDAO.class);
+    private IRecordsQueryDAO getRecordsQueryDAO() {
+        if (recordsQueryDAO == null) {
+            this.recordsQueryDAO = moduleManager.find(StorageModule.NAME)
+                .provider()
+                .getService(IRecordsQueryDAO.class);
         }
-        return topNRecordsQueryDAO;
+        return recordsQueryDAO;
     }
 
-    public List<SelectedRecord> readSampledRecords(TopNCondition condition, Duration duration) throws IOException {
-        return getTopNRecordsQueryDAO().readSampledRecords(
+    public List<Record> readRecords(RecordCondition condition, Duration duration) throws IOException {
+        return getRecordsQueryDAO().readRecords(
             condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
     }
-}
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
index 31c55d56a6..035b1f94ae 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopNRecordsQueryService.java
@@ -20,34 +20,40 @@ package org.apache.skywalking.oap.server.core.query;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
 import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
 import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
 import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 public class TopNRecordsQueryService implements Service {
     private final ModuleManager moduleManager;
-    private ITopNRecordsQueryDAO topNRecordsQueryDAO;
+    private IRecordsQueryDAO recordsQueryDAO;
 
     public TopNRecordsQueryService(ModuleManager manager) {
         this.moduleManager = manager;
     }
 
-    private ITopNRecordsQueryDAO getTopNRecordsQueryDAO() {
-        if (topNRecordsQueryDAO == null) {
-            this.topNRecordsQueryDAO = moduleManager.find(StorageModule.NAME)
+    private IRecordsQueryDAO getRecordsQueryDAO() {
+        if (recordsQueryDAO == null) {
+            this.recordsQueryDAO = moduleManager.find(StorageModule.NAME)
                                                     .provider()
-                                                    .getService(ITopNRecordsQueryDAO.class);
+                                                    .getService(IRecordsQueryDAO.class);
         }
-        return topNRecordsQueryDAO;
+        return recordsQueryDAO;
     }
 
     public List<SelectedRecord> readSampledRecords(TopNCondition condition, Duration duration) throws IOException {
-        return getTopNRecordsQueryDAO().readSampledRecords(
-            condition, ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
+        final List<Record> records = getRecordsQueryDAO().readRecords(
+            new RecordCondition(condition), ValueColumnMetadata.INSTANCE.getValueCName(condition.getName()), duration);
+        return records.stream().filter(Objects::nonNull).map(Record::toSelectedRecord).collect(Collectors.toList());
     }
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java
new file mode 100644
index 0000000000..1b9aa08cdf
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/RecordCondition.java
@@ -0,0 +1,62 @@
+/*
+ * 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.query.input;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.core.query.enumeration.Order;
+import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
+
+/**
+ * Record query condition.
+ *
+ * @since 9.3.0
+ */
+@Setter
+@Getter
+public class RecordCondition {
+    /**
+     * Metrics name
+     */
+    private String name;
+    /**
+     * Follow {@link Entity} definition description.
+     * The owner of the sampled records.
+     */
+    private Entity parentEntity;
+    private int topN;
+    private Order order;
+
+    public RecordCondition() {
+    }
+
+    public RecordCondition(TopNCondition condition) {
+        this.name = condition.getName();
+        if (StringUtil.isNotEmpty(condition.getParentService())) {
+            final Entity entity = new Entity();
+            entity.setScope(condition.getScope() == null ? Scope.Service : condition.getScope());
+            entity.setServiceName(condition.getParentService());
+            entity.setNormal(condition.isNormal());
+            this.parentEntity = entity;
+        }
+        this.topN = condition.getTopN();
+        this.order = condition.getOrder();
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Record.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Record.java
new file mode 100644
index 0000000000..f9ad565964
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Record.java
@@ -0,0 +1,53 @@
+/*
+ * 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.query.type;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class Record {
+    /**
+     * Literal string name for visualization.
+     */
+    private String name;
+    /**
+     * ID of this record.
+     */
+    private String id;
+    /**
+     * Usually an integer value as this is a metric to measure this entity ID.
+     */
+    private String value;
+    /**
+     * Have value, Only if the record has related trace id.
+     * UI should show this as an attached value.
+     */
+    private String refId;
+
+    public SelectedRecord toSelectedRecord() {
+        final SelectedRecord result = new SelectedRecord();
+        result.setName(getName());
+        result.setId(getId());
+        result.setRefId(getRefId());
+        result.setValue(getValue());
+        return result;
+    }
+}
\ No newline at end of file
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 928650bd06..534d9b7510 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
@@ -35,7 +35,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -67,7 +67,7 @@ public class StorageModule extends ModuleDefine {
             IMetadataQueryDAO.class,
             IAggregationQueryDAO.class,
             IAlarmQueryDAO.class,
-            ITopNRecordsQueryDAO.class,
+            IRecordsQueryDAO.class,
             ILogQueryDAO.class,
             IProfileTaskQueryDAO.class,
             IProfileTaskLogQueryDAO.class,
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IRecordsQueryDAO.java
similarity index 75%
rename from oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java
rename to oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IRecordsQueryDAO.java
index 7805bb013b..20dd3aa89e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopNRecordsQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IRecordsQueryDAO.java
@@ -23,8 +23,8 @@ import java.util.List;
 import org.apache.skywalking.oap.server.core.analysis.Stream;
 import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
-import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
-import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 /**
@@ -32,8 +32,8 @@ import org.apache.skywalking.oap.server.library.module.Service;
  *
  * @since 8.0.0
  */
-public interface ITopNRecordsQueryDAO extends Service {
-    List<SelectedRecord> readSampledRecords(TopNCondition condition,
-                                            final String valueColumnName,
-                                            Duration duration) throws IOException;
+public interface IRecordsQueryDAO extends Service {
+    List<Record> readRecords(RecordCondition condition,
+                             final String valueColumnName,
+                             Duration duration) throws IOException;
 }
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java
index 039c53c37c..4d69c69966 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/CoreModuleTest.java
@@ -26,6 +26,6 @@ public class CoreModuleTest {
     public void testOpenServiceList() {
         CoreModule coreModule = new CoreModule();
 
-        Assert.assertEquals(36, coreModule.services().length);
+        Assert.assertEquals(37, coreModule.services().length);
     }
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
index f4f694a96e..882016cf17 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java
@@ -41,6 +41,7 @@ import org.apache.skywalking.oap.query.graphql.resolver.ProfileMutation;
 import org.apache.skywalking.oap.query.graphql.resolver.ProfileQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.Query;
 import org.apache.skywalking.oap.query.graphql.resolver.OndemandLogQuery;
+import org.apache.skywalking.oap.query.graphql.resolver.RecordsQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.TopNRecordsQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.TopologyQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.TraceQuery;
@@ -121,7 +122,9 @@ public class GraphQLQueryProvider extends ModuleProvider {
                      .file("query-protocol/metadata-v2.graphqls")
                      .resolvers(metadataQueryV2)
                      .file("query-protocol/ebpf-profiling.graphqls")
-                     .resolvers(new EBPFProcessProfilingQuery(getManager()), new EBPFProcessProfilingMutation(getManager()));
+                     .resolvers(new EBPFProcessProfilingQuery(getManager()), new EBPFProcessProfilingMutation(getManager()))
+                     .file("query-protocol/record.graphqls")
+                     .resolvers(new RecordsQuery(getManager()));
 
         if (config.isEnableOnDemandPodLog()) {
             schemaBuilder
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
index bcdd34cd08..36eb5de188 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java
@@ -23,6 +23,9 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
@@ -30,14 +33,16 @@ import org.apache.skywalking.oap.server.core.query.MetricDefinition;
 import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
 import org.apache.skywalking.oap.server.core.query.MetricsQueryService;
 import org.apache.skywalking.oap.server.core.query.PointOfTime;
-import org.apache.skywalking.oap.server.core.query.TopNRecordsQueryService;
+import org.apache.skywalking.oap.server.core.query.RecordQueryService;
 import org.apache.skywalking.oap.server.core.query.enumeration.MetricsType;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
 import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
 import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
 import org.apache.skywalking.oap.server.core.query.type.HeatMap;
 import org.apache.skywalking.oap.server.core.query.type.KVInt;
 import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
+import org.apache.skywalking.oap.server.core.query.type.Record;
 import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
@@ -50,7 +55,7 @@ public class MetricsQuery implements GraphQLQueryResolver {
     private final ModuleManager moduleManager;
     private MetricsQueryService metricsQueryService;
     private AggregationQueryService queryService;
-    private TopNRecordsQueryService topNRecordsQueryService;
+    private RecordQueryService recordQueryService;
     private MetricsMetadataQueryService metricsMetadataQueryService;
 
     public MetricsQuery(ModuleManager moduleManager) {
@@ -75,13 +80,13 @@ public class MetricsQuery implements GraphQLQueryResolver {
         return queryService;
     }
 
-    private TopNRecordsQueryService getTopNRecordsQueryService() {
-        if (topNRecordsQueryService == null) {
-            this.topNRecordsQueryService = moduleManager.find(CoreModule.NAME)
+    private RecordQueryService getRecordQueryService() {
+        if (recordQueryService == null) {
+            this.recordQueryService = moduleManager.find(CoreModule.NAME)
                                                         .provider()
-                                                        .getService(TopNRecordsQueryService.class);
+                                                        .getService(RecordQueryService.class);
         }
-        return topNRecordsQueryService;
+        return recordQueryService;
     }
 
     private MetricsQueryService getMetricsQueryService() {
@@ -214,11 +219,15 @@ public class MetricsQuery implements GraphQLQueryResolver {
 
     /**
      * Read the sampled records.
+     *
+     * @since 9.3.0 This query is replaced by {@link RecordQueryService#readRecords(RecordCondition, Duration)}
      */
+    @Deprecated
     public List<SelectedRecord> readSampledRecords(TopNCondition condition, Duration duration) throws IOException {
         if (MetricsType.UNKNOWN.equals(typeOfMetrics(condition.getName()))) {
             return Collections.emptyList();
         }
-        return getTopNRecordsQueryService().readSampledRecords(condition, duration);
+        final List<Record> records = getRecordQueryService().readRecords(new RecordCondition(condition), duration);
+        return records.stream().filter(Objects::nonNull).map(Record::toSelectedRecord).collect(Collectors.toList());
     }
 }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/RecordsQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/RecordsQuery.java
new file mode 100644
index 0000000000..b0094e674b
--- /dev/null
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/RecordsQuery.java
@@ -0,0 +1,52 @@
+/*
+ * 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.query.graphql.resolver;
+
+import graphql.kickstart.tools.GraphQLQueryResolver;
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.query.RecordQueryService;
+import org.apache.skywalking.oap.server.core.query.input.Duration;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+
+import java.io.IOException;
+import java.util.List;
+
+public class RecordsQuery implements GraphQLQueryResolver {
+    private ModuleManager moduleManager;
+    private RecordQueryService recordQueryService;
+
+    public RecordsQuery(ModuleManager moduleManager) {
+        this.moduleManager = moduleManager;
+    }
+
+    private RecordQueryService getRecordQueryService() {
+        if (recordQueryService == null) {
+            recordQueryService = moduleManager.find(CoreModule.NAME)
+                .provider()
+                .getService(RecordQueryService.class);
+        }
+        return recordQueryService;
+    }
+
+    public List<Record> readRecords(RecordCondition condition, Duration duration) throws IOException {
+        return getRecordQueryService().readRecords(condition, duration);
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
index 2c541beae6..f6ed76588f 160000
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
@@ -1 +1 @@
-Subproject commit 2c541beae657306127f07af127d179492a1d7cf9
+Subproject commit f6ed76588f2aa147c0b59a3b497526b317ee7fb9
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBTopNRecordsQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java
similarity index 75%
rename from oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBTopNRecordsQueryDAO.java
rename to oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java
index e5aee4c1b5..3955fac142 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBTopNRecordsQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java
@@ -23,14 +23,12 @@ import org.apache.skywalking.banyandb.v1.client.DataPoint;
 import org.apache.skywalking.banyandb.v1.client.MeasureQuery;
 import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse;
 import org.apache.skywalking.banyandb.v1.client.TimestampRange;
-import org.apache.skywalking.oap.server.core.analysis.IDManager;
-import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
 import org.apache.skywalking.oap.server.core.analysis.topn.TopN;
 import org.apache.skywalking.oap.server.core.query.enumeration.Order;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
-import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
-import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.util.StringUtil;
 import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.AbstractBanyanDBDAO;
 import org.apache.skywalking.oap.server.storage.plugin.banyandb.util.ByteUtil;
@@ -41,25 +39,23 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-public class BanyanDBTopNRecordsQueryDAO extends AbstractBanyanDBDAO implements ITopNRecordsQueryDAO {
-    private static final Set<String> TAGS = ImmutableSet.of(TopN.TIME_BUCKET, TopN.SERVICE_ID, TopN.STATEMENT, TopN.TRACE_ID);
+public class BanyanDBRecordsQueryDAO extends AbstractBanyanDBDAO implements IRecordsQueryDAO {
+    private static final Set<String> TAGS = ImmutableSet.of(TopN.TIME_BUCKET, TopN.ENTITY_ID, TopN.STATEMENT, TopN.TRACE_ID);
 
-    public BanyanDBTopNRecordsQueryDAO(BanyanDBStorageClient client) {
+    public BanyanDBRecordsQueryDAO(BanyanDBStorageClient client) {
         super(client);
     }
 
     @Override
-    public List<SelectedRecord> readSampledRecords(TopNCondition condition, String valueColumnName, Duration duration) throws IOException {
+    public List<Record> readRecords(RecordCondition condition, String valueColumnName, Duration duration) throws IOException {
         final String modelName = condition.getName();
         final TimestampRange timestampRange = new TimestampRange(duration.getStartTimestamp(), duration.getEndTimestamp());
         MeasureQueryResponse resp = query(modelName, TAGS,
                 Collections.singleton(valueColumnName), timestampRange, new QueryBuilder<MeasureQuery>() {
                     @Override
                     protected void apply(MeasureQuery query) {
-                        if (StringUtil.isNotEmpty(condition.getParentService())) {
-                            final String serviceId =
-                                    IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
-                            query.and(eq(TopN.SERVICE_ID, serviceId));
+                        if (condition.getParentEntity() != null && condition.getParentEntity().buildId() != null) {
+                            query.and(eq(TopN.ENTITY_ID, condition.getParentEntity().buildId()));
                         }
                         if (condition.getOrder() == Order.DES) {
                             query.topN(condition.getTopN(), valueColumnName);
@@ -85,13 +81,14 @@ public class BanyanDBTopNRecordsQueryDAO extends AbstractBanyanDBDAO implements
             throw new IOException("field spec is not registered");
         }
 
-        List<SelectedRecord> results = new ArrayList<>(condition.getTopN());
+        List<Record> results = new ArrayList<>(condition.getTopN());
 
         for (final DataPoint dataPoint : resp.getDataPoints()) {
-            SelectedRecord record = new SelectedRecord();
+            Record record = new Record();
+            final String refId = dataPoint.getTagValue(TopN.TRACE_ID);
             record.setName(dataPoint.getTagValue(TopN.STATEMENT));
-            record.setRefId(dataPoint.getTagValue(TopN.TRACE_ID));
-            record.setId(dataPoint.getTagValue(Metrics.ENTITY_ID));
+            record.setRefId(StringUtil.isEmpty(refId) ? "" : refId);
+            record.setId(record.getRefId());
             record.setValue(extractFieldValueAsString(spec, valueColumnName, dataPoint));
             results.add(record);
         }
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java
index 8e3977407c..54d70fd2b5 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java
@@ -43,7 +43,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -130,7 +130,7 @@ public class BanyanDBStorageProvider extends ModuleProvider {
         this.registerServiceImplementation(IHistoryDeleteDAO.class, new BanyanDBHistoryDeleteDAO());
         this.registerServiceImplementation(IMetricsQueryDAO.class, new BanyanDBMetricsQueryDAO(client));
         this.registerServiceImplementation(IAggregationQueryDAO.class, new BanyanDBAggregationQueryDAO(client));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new BanyanDBTopNRecordsQueryDAO(client));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new BanyanDBRecordsQueryDAO(client));
         this.registerServiceImplementation(IZipkinQueryDAO.class, new BanyanDBZipkinQueryDAO(client));
     }
 
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 451c481f58..107bdb3a6f 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
@@ -48,7 +48,7 @@ import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
@@ -80,7 +80,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.Profi
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ProfileTaskQueryEsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ProfileThreadSnapshotQueryEsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopNRecordsQueryEsDAO;
+import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.RecordsQueryEsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TopologyQueryEsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TraceQueryEsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.UITemplateManagementEsDAO;
@@ -190,7 +190,7 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
         this.registerServiceImplementation(IMetadataQueryDAO.class, new MetadataQueryEsDAO(elasticSearchClient, config));
         this.registerServiceImplementation(IAggregationQueryDAO.class, new AggregationQueryEsDAO(elasticSearchClient));
         this.registerServiceImplementation(IAlarmQueryDAO.class, new AlarmQueryEsDAO(elasticSearchClient));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new TopNRecordsQueryEsDAO(elasticSearchClient));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new RecordsQueryEsDAO(elasticSearchClient));
         this.registerServiceImplementation(ILogQueryDAO.class, new LogQueryEsDAO(elasticSearchClient));
         this.registerServiceImplementation(
             IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(elasticSearchClient, config
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
similarity index 75%
rename from oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java
rename to oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
index a866216e23..e85a062b07 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopNRecordsQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
@@ -22,7 +22,9 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import org.apache.skywalking.oap.server.library.util.StringUtil;
+
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
 import org.apache.skywalking.library.elasticsearch.requests.search.BoolQueryBuilder;
 import org.apache.skywalking.library.elasticsearch.requests.search.Query;
 import org.apache.skywalking.library.elasticsearch.requests.search.Search;
@@ -30,26 +32,24 @@ import org.apache.skywalking.library.elasticsearch.requests.search.SearchBuilder
 import org.apache.skywalking.library.elasticsearch.requests.search.Sort;
 import org.apache.skywalking.library.elasticsearch.response.search.SearchHit;
 import org.apache.skywalking.library.elasticsearch.response.search.SearchResponse;
-import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.topn.TopN;
 import org.apache.skywalking.oap.server.core.query.enumeration.Order;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
-import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
-import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.IndexController;
 
-public class TopNRecordsQueryEsDAO extends EsDAO implements ITopNRecordsQueryDAO {
-    public TopNRecordsQueryEsDAO(ElasticSearchClient client) {
+public class RecordsQueryEsDAO extends EsDAO implements IRecordsQueryDAO {
+    public RecordsQueryEsDAO(ElasticSearchClient client) {
         super(client);
     }
 
     @Override
-    public List<SelectedRecord> readSampledRecords(final TopNCondition condition,
-                                                   final String valueColumnName,
-                                                   final Duration duration) throws IOException {
+    public List<Record> readRecords(final RecordCondition condition,
+                                           final String valueColumnName,
+                                           final Duration duration) throws IOException {
         final BoolQueryBuilder query =
             Query.bool()
                  .must(Query.range(TopN.TIME_BUCKET)
@@ -59,10 +59,8 @@ public class TopNRecordsQueryEsDAO extends EsDAO implements ITopNRecordsQueryDAO
             query.must(Query.term(IndexController.LogicIndicesRegister.RECORD_TABLE_NAME, condition.getName()));
         }
 
-        if (StringUtil.isNotEmpty(condition.getParentService())) {
-            final String serviceId =
-                IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
-            query.must(Query.term(TopN.SERVICE_ID, serviceId));
+        if (condition.getParentEntity() != null && condition.getParentEntity().buildId() != null) {
+            query.must(Query.term(TopN.ENTITY_ID, condition.getParentEntity().buildId()));
         }
 
         final SearchBuilder search =
@@ -79,13 +77,14 @@ public class TopNRecordsQueryEsDAO extends EsDAO implements ITopNRecordsQueryDAO
             search.build()
         );
 
-        List<SelectedRecord> results = new ArrayList<>(condition.getTopN());
+        List<Record> results = new ArrayList<>(condition.getTopN());
 
         for (SearchHit searchHit : response.getHits().getHits()) {
-            SelectedRecord record = new SelectedRecord();
+            Record record = new Record();
             final Map<String, Object> sourceAsMap = searchHit.getSource();
             record.setName((String) sourceAsMap.get(TopN.STATEMENT));
-            record.setRefId((String) sourceAsMap.get(TopN.TRACE_ID));
+            final String refId = (String) sourceAsMap.get(TopN.TRACE_ID);
+            record.setRefId(StringUtil.isEmpty(refId) ? "" : refId);
             record.setId(record.getRefId());
             record.setValue(sourceAsMap.get(valueColumnName).toString());
             results.add(record);
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 2fa67ec25f..6aa052621d 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
@@ -45,7 +45,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -75,7 +75,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileThre
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2StorageDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TableInstaller;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2RecordsQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopologyQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TraceQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2UITemplateManagementDAO;
@@ -147,7 +147,7 @@ public class H2StorageProvider extends ModuleProvider {
         this.registerServiceImplementation(IAlarmQueryDAO.class, new H2AlarmQueryDAO(h2Client, getManager()));
         this.registerServiceImplementation(
             IHistoryDeleteDAO.class, new H2HistoryDeleteDAO(h2Client));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new H2TopNRecordsQueryDAO(h2Client));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new H2RecordsQueryDAO(h2Client));
         this.registerServiceImplementation(
             ILogQueryDAO.class,
             new H2LogQueryDAO(h2Client, getManager()));
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/H2TopNRecordsQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2RecordsQueryDAO.java
similarity index 71%
rename from oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopNRecordsQueryDAO.java
rename to oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2RecordsQueryDAO.java
index 4f4cb0fb8d..48fa495ef9 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TopNRecordsQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2RecordsQueryDAO.java
@@ -24,34 +24,35 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.skywalking.oap.server.library.util.StringUtil;
-import org.apache.skywalking.oap.server.core.analysis.IDManager;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.query.input.RecordCondition;
+import org.apache.skywalking.oap.server.core.query.type.Record;
 import org.apache.skywalking.oap.server.core.analysis.topn.TopN;
 import org.apache.skywalking.oap.server.core.query.enumeration.Order;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
-import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
-import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
-public class H2TopNRecordsQueryDAO implements ITopNRecordsQueryDAO {
+@Slf4j
+public class H2RecordsQueryDAO implements IRecordsQueryDAO {
     private JDBCHikariCPClient h2Client;
 
-    public H2TopNRecordsQueryDAO(JDBCHikariCPClient h2Client) {
+    public H2RecordsQueryDAO(JDBCHikariCPClient h2Client) {
         this.h2Client = h2Client;
     }
 
     @Override
-    public List<SelectedRecord> readSampledRecords(final TopNCondition condition,
-                                                   final String valueColumnName,
-                                                   final Duration duration) throws IOException {
+    public List<Record> readRecords(final RecordCondition condition,
+                                           final String valueColumnName,
+                                           final Duration duration) throws IOException {
         StringBuilder sql = new StringBuilder("select * from " + condition.getName() + " where ");
         List<Object> parameters = new ArrayList<>(10);
 
-        if (StringUtil.isNotEmpty(condition.getParentService())) {
-            sql.append(" service_id = ? and");
-            final String serviceId = IDManager.ServiceID.buildId(condition.getParentService(), condition.isNormal());
-            parameters.add(serviceId);
+        if (condition.getParentEntity() != null && condition.getParentEntity().buildId() != null) {
+            sql.append(" ").append(TopN.ENTITY_ID).append(" = ? and");
+            parameters.add(condition.getParentEntity().buildId());
         }
 
         sql.append(" ").append(TopN.TIME_BUCKET).append(" >= ?");
@@ -67,14 +68,15 @@ public class H2TopNRecordsQueryDAO implements ITopNRecordsQueryDAO {
         }
         sql.append(" limit ").append(condition.getTopN());
 
-        List<SelectedRecord> results = new ArrayList<>();
+        List<Record> results = new ArrayList<>();
         try (Connection connection = h2Client.getConnection()) {
             try (ResultSet resultSet = h2Client.executeQuery(
                 connection, sql.toString(), parameters.toArray(new Object[0]))) {
                 while (resultSet.next()) {
-                    SelectedRecord record = new SelectedRecord();
+                    Record record = new Record();
                     record.setName(resultSet.getString(TopN.STATEMENT));
-                    record.setRefId(resultSet.getString(TopN.TRACE_ID));
+                    final String refId = resultSet.getString(TopN.TRACE_ID);
+                    record.setRefId(StringUtil.isEmpty(refId) ? "" : refId);
                     record.setId(record.getRefId());
                     record.setValue(resultSet.getString(valueColumnName));
                     results.add(record);
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLStorageProvider.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLStorageProvider.java
index d82f4ee076..2d065556ec 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLStorageProvider.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLStorageProvider.java
@@ -44,7 +44,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -69,7 +69,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileTask
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2StorageDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2RecordsQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopologyQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2UITemplateManagementDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ZipkinQueryDAO;
@@ -133,7 +133,7 @@ public class MySQLStorageProvider extends ModuleProvider {
         this.registerServiceImplementation(IAlarmQueryDAO.class, new MySQLAlarmQueryDAO(mysqlClient, getManager()));
         this.registerServiceImplementation(
             IHistoryDeleteDAO.class, new H2HistoryDeleteDAO(mysqlClient));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new H2TopNRecordsQueryDAO(mysqlClient));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new H2RecordsQueryDAO(mysqlClient));
         this.registerServiceImplementation(
             ILogQueryDAO.class,
             new MySQLLogQueryDAO(mysqlClient, getManager()));
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/postgresql/PostgreSQLStorageProvider.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/postgresql/PostgreSQLStorageProvider.java
index 788a81d61a..34944da9f5 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/postgresql/PostgreSQLStorageProvider.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/postgresql/PostgreSQLStorageProvider.java
@@ -44,7 +44,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -68,7 +68,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileTask
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2StorageDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2RecordsQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopologyQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2UITemplateManagementDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ZipkinQueryDAO;
@@ -133,7 +133,7 @@ public class PostgreSQLStorageProvider extends ModuleProvider {
         this.registerServiceImplementation(IAlarmQueryDAO.class, new PostgreSQLAlarmQueryDAO(postgresqlClient, getManager()));
         this.registerServiceImplementation(
                 IHistoryDeleteDAO.class, new H2HistoryDeleteDAO(postgresqlClient));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new H2TopNRecordsQueryDAO(postgresqlClient));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new H2RecordsQueryDAO(postgresqlClient));
         this.registerServiceImplementation(
                 ILogQueryDAO.class,
                 new PostgreSQLLogQueryDAO(postgresqlClient, getManager()));
diff --git a/oap-server/server-storage-plugin/storage-shardingsphere-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/shardingsphere/mysql/MySQLShardingStorageProvider.java b/oap-server/server-storage-plugin/storage-shardingsphere-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/shardingsphere/mysql/MySQLShardingStorageProvider.java
index 91e05d0ec6..41a4e10521 100644
--- a/oap-server/server-storage-plugin/storage-shardingsphere-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/shardingsphere/mysql/MySQLShardingStorageProvider.java
+++ b/oap-server/server-storage-plugin/storage-shardingsphere-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/shardingsphere/mysql/MySQLShardingStorageProvider.java
@@ -47,7 +47,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -71,7 +71,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileTask
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2StorageDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2RecordsQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2UITemplateManagementDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.mysql.MySQLAlarmQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
@@ -134,7 +134,7 @@ public class MySQLShardingStorageProvider extends ModuleProvider {
         this.registerServiceImplementation(IAlarmQueryDAO.class, new MySQLAlarmQueryDAO(mysqlClient, getManager()));
         this.registerServiceImplementation(
             IHistoryDeleteDAO.class, new H2HistoryDeleteDAO(mysqlClient));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new H2TopNRecordsQueryDAO(mysqlClient));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new H2RecordsQueryDAO(mysqlClient));
         this.registerServiceImplementation(
             ILogQueryDAO.class,
             new MySQLShardingLogQueryDAO(mysqlClient, getManager()));
diff --git a/oap-server/server-storage-plugin/storage-tidb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/tidb/TiDBStorageProvider.java b/oap-server/server-storage-plugin/storage-tidb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/tidb/TiDBStorageProvider.java
index 3871c9182f..18a42a5533 100644
--- a/oap-server/server-storage-plugin/storage-tidb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/tidb/TiDBStorageProvider.java
+++ b/oap-server/server-storage-plugin/storage-tidb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/tidb/TiDBStorageProvider.java
@@ -45,7 +45,7 @@ import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.core.storage.query.IRecordsQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
@@ -70,7 +70,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileTask
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileThreadSnapshotQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2StorageDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TagAutoCompleteQueryDAO;
-import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopNRecordsQueryDAO;
+import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2RecordsQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopologyQueryDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2UITemplateManagementDAO;
 import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ZipkinQueryDAO;
@@ -137,7 +137,7 @@ public class TiDBStorageProvider extends ModuleProvider {
         this.registerServiceImplementation(IAlarmQueryDAO.class, new MySQLAlarmQueryDAO(mysqlClient, getManager()));
         this.registerServiceImplementation(
             IHistoryDeleteDAO.class, new H2HistoryDeleteDAO(mysqlClient));
-        this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new H2TopNRecordsQueryDAO(mysqlClient));
+        this.registerServiceImplementation(IRecordsQueryDAO.class, new H2RecordsQueryDAO(mysqlClient));
         this.registerServiceImplementation(
             ILogQueryDAO.class,
             new MySQLLogQueryDAO(mysqlClient, getManager()));
diff --git a/test/e2e-v2/cases/browser/expected/trace-detail.yml b/test/e2e-v2/cases/browser/expected/trace-detail.yml
index 3d2bb3de98..4a0d3d918e 100644
--- a/test/e2e-v2/cases/browser/expected/trace-detail.yml
+++ b/test/e2e-v2/cases/browser/expected/trace-detail.yml
@@ -36,6 +36,7 @@ spans:
       - key: url
         value: http://provider:9091/info
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: 0
@@ -65,4 +66,5 @@ spans:
       - key: http.status.code
         value: "200"
     logs: []
+    attachedevents: []
 {{- end }}
diff --git a/test/e2e-v2/cases/go/expected/trace-correlation-detail.yml b/test/e2e-v2/cases/go/expected/trace-correlation-detail.yml
index 40b090db6c..8e8d25a6c1 100644
--- a/test/e2e-v2/cases/go/expected/trace-correlation-detail.yml
+++ b/test/e2e-v2/cases/go/expected/trace-correlation-detail.yml
@@ -36,6 +36,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -59,6 +60,7 @@ spans:
         value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -90,6 +92,7 @@ spans:
         value: "200"
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -115,6 +118,7 @@ spans:
         value: "200"
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -144,4 +148,5 @@ spans:
       value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
diff --git a/test/e2e-v2/cases/meter/expected/record-has-value.yml b/test/e2e-v2/cases/meter/expected/record-has-value.yml
index 76e239cfa3..4551156ea0 100644
--- a/test/e2e-v2/cases/meter/expected/record-has-value.yml
+++ b/test/e2e-v2/cases/meter/expected/record-has-value.yml
@@ -20,10 +20,10 @@
   - key: name
     value: {{ notEmpty .value}}
   - key: id
-    value: ""
+    value: {{ notEmpty .value}}
   - key: value
     value: {{ notEmpty .value}}
   - key: refid
-    value:
+    value: {{ notEmpty .value}}
   {{- end }}
 {{- end }}
\ No newline at end of file
diff --git a/test/e2e-v2/cases/meter/meter-cases.yaml b/test/e2e-v2/cases/meter/meter-cases.yaml
index 0fa6fe31e7..ace00892bc 100644
--- a/test/e2e-v2/cases/meter/meter-cases.yaml
+++ b/test/e2e-v2/cases/meter/meter-cases.yaml
@@ -43,7 +43,7 @@
         swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=cache_access_cpm  --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0  | yq e 'to_entries' -
       expected: expected/metrics-has-value.yml
     - query: |
-        swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics sampled-record  --name=top_n_cache_write_command    --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0 |  yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+        swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql records list --name=top_n_cache_write_command    --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0 |  yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
       expected: expected/record-has-value.yml
       # virtual database
     - query: |
diff --git a/test/e2e-v2/cases/mysql/expected/db-has-value.yml b/test/e2e-v2/cases/mysql/expected/db-has-value.yml
index a9ec0add46..80e0a6dac9 100644
--- a/test/e2e-v2/cases/mysql/expected/db-has-value.yml
+++ b/test/e2e-v2/cases/mysql/expected/db-has-value.yml
@@ -17,7 +17,13 @@
 - key: 0
   value:
   {{- contains .value }}
-  - key: {{ notEmpty .key }}
+  - key: name
     value: {{ notEmpty .value }}
+  - key: value
+    value: {{ notEmpty .value }}
+  - key: id
+    value: ""
+  - key: refid
+    value: ""
   {{- end }}
 {{- end }}
diff --git a/test/e2e-v2/cases/mysql/mysql-cases.yaml b/test/e2e-v2/cases/mysql/mysql-cases.yaml
index ea3d7839f9..360d349571 100644
--- a/test/e2e-v2/cases/mysql/mysql-cases.yaml
+++ b/test/e2e-v2/cases/mysql/mysql-cases.yaml
@@ -54,5 +54,5 @@
     - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=meter_mysql_connects_available --service-name=mysql::root[root] |yq e 'to_entries' -
       expected:  expected/metrics-has-value.yml
     # slow sql
-    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics sampled-record --name=top_n_database_statement |yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql records list --name=top_n_database_statement |yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
       expected:  expected/db-has-value.yml
\ No newline at end of file
diff --git a/test/e2e-v2/cases/php/expected/trace-info-detail.yml b/test/e2e-v2/cases/php/expected/trace-info-detail.yml
index 1315e4b7c8..bb8fade225 100644
--- a/test/e2e-v2/cases/php/expected/trace-info-detail.yml
+++ b/test/e2e-v2/cases/php/expected/trace-info-detail.yml
@@ -36,6 +36,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -57,6 +58,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -86,5 +88,6 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
 
diff --git a/test/e2e-v2/cases/postgresql/expected/db-has-value.yml b/test/e2e-v2/cases/postgresql/expected/db-has-value.yml
index a9ec0add46..80e0a6dac9 100644
--- a/test/e2e-v2/cases/postgresql/expected/db-has-value.yml
+++ b/test/e2e-v2/cases/postgresql/expected/db-has-value.yml
@@ -17,7 +17,13 @@
 - key: 0
   value:
   {{- contains .value }}
-  - key: {{ notEmpty .key }}
+  - key: name
     value: {{ notEmpty .value }}
+  - key: value
+    value: {{ notEmpty .value }}
+  - key: id
+    value: ""
+  - key: refid
+    value: ""
   {{- end }}
 {{- end }}
diff --git a/test/e2e-v2/cases/postgresql/postgresql-cases.yaml b/test/e2e-v2/cases/postgresql/postgresql-cases.yaml
index 33d0c3a46c..ca9147344e 100644
--- a/test/e2e-v2/cases/postgresql/postgresql-cases.yaml
+++ b/test/e2e-v2/cases/postgresql/postgresql-cases.yaml
@@ -57,5 +57,5 @@
     - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics multiple-linear --name=meter_pg_active_sessions --labels=postgres --service-name=postgresql::postgres:5432 |yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
       expected: expected/metrics-has-value-label.yml	
      # slow sql
-    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics sampled-record --name=top_n_database_statement |yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql records list --name=top_n_database_statement |yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
       expected:  expected/db-has-value.yml
diff --git a/test/e2e-v2/cases/python/expected/trace-test-detail.yml b/test/e2e-v2/cases/python/expected/trace-test-detail.yml
index 061afa5b2a..ba53891ca0 100644
--- a/test/e2e-v2/cases/python/expected/trace-test-detail.yml
+++ b/test/e2e-v2/cases/python/expected/trace-test-detail.yml
@@ -36,6 +36,7 @@ spans:
         value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: {{ .spanid }}
@@ -61,6 +62,7 @@ spans:
         value: "200"
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: {{ .spanid }}
@@ -90,6 +92,7 @@ spans:
         value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: {{ .spanid }}
@@ -113,6 +116,7 @@ spans:
         value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: {{ .spanid }}
@@ -140,6 +144,7 @@ spans:
         value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: {{ .spanid }}
@@ -165,6 +170,7 @@ spans:
         value: "200"
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ notEmpty .segmentid }}
     spanid: {{ .spanid }}
@@ -192,4 +198,5 @@ spans:
         value: POST
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
diff --git a/test/e2e-v2/cases/satellite/native-protocols/expected/trace-info-detail.yml b/test/e2e-v2/cases/satellite/native-protocols/expected/trace-info-detail.yml
index 95b9bd98a5..037edc6fc8 100644
--- a/test/e2e-v2/cases/satellite/native-protocols/expected/trace-info-detail.yml
+++ b/test/e2e-v2/cases/satellite/native-protocols/expected/trace-info-detail.yml
@@ -65,4 +65,5 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
diff --git a/test/e2e-v2/cases/satellite/native-protocols/expected/trace-users-detail.yml b/test/e2e-v2/cases/satellite/native-protocols/expected/trace-users-detail.yml
index 9bc9f556af..d26775c9ce 100644
--- a/test/e2e-v2/cases/satellite/native-protocols/expected/trace-users-detail.yml
+++ b/test/e2e-v2/cases/satellite/native-protocols/expected/trace-users-detail.yml
@@ -38,4 +38,5 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
diff --git a/test/e2e-v2/cases/simple/expected/trace-users-detail.yml b/test/e2e-v2/cases/simple/expected/trace-users-detail.yml
index 0905893c03..437b9dd111 100644
--- a/test/e2e-v2/cases/simple/expected/trace-users-detail.yml
+++ b/test/e2e-v2/cases/simple/expected/trace-users-detail.yml
@@ -38,6 +38,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -61,6 +62,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -90,4 +92,5 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
diff --git a/test/e2e-v2/cases/storage/expected/trace-users-detail.yml b/test/e2e-v2/cases/storage/expected/trace-users-detail.yml
index 0905893c03..437b9dd111 100644
--- a/test/e2e-v2/cases/storage/expected/trace-users-detail.yml
+++ b/test/e2e-v2/cases/storage/expected/trace-users-detail.yml
@@ -38,6 +38,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -61,6 +62,7 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   - traceid: {{ notEmpty .traceid }}
     segmentid: {{ .segmentid }}
     spanid: {{ .spanid }}
@@ -90,4 +92,5 @@ spans:
         value: {{ notEmpty .value }}
       {{- end }}
     logs: []
+    attachedevents: []
   {{- end }}
diff --git a/test/e2e-v2/script/env b/test/e2e-v2/script/env
index f916e78c1d..7c08ebc39c 100644
--- a/test/e2e-v2/script/env
+++ b/test/e2e-v2/script/env
@@ -25,4 +25,4 @@ SW_KUBERNETES_COMMIT_SHA=0f3ec68e5a7e1608cec8688716b848ed15e971e5
 SW_ROVER_COMMIT=d956eaede57b62108b78bca48045bd09ba88e653
 SW_BANYANDB_COMMIT=5a326d7e36a008c5ea10e3ae506309cb29733c53
 
-SW_CTL_COMMIT=a7c4ccae106e4a5a0b6296f860396f289444058d
+SW_CTL_COMMIT=e684fae0107045fc23799146d62f04cb68bd5a3b