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

wankai 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 98ef399410 Support tracing topology query for debugging (#12413)
98ef399410 is described below

commit 98ef399410437b097c417930ea9b4f02c2af8acf
Author: Wan Kai <[email protected]>
AuthorDate: Thu Jul 4 15:09:53 2024 +0800

    Support tracing topology query for debugging (#12413)
---
 docs/en/api/query-protocol.md                      |  13 +-
 docs/en/changes/changes.md                         |   1 +
 docs/en/debugging/query-tracing.md                 | 403 ++++++++++++++++++---
 .../server/core/query/EndpointTopologyBuilder.java |  87 +++++
 .../server/core/query/ProcessTopologyBuilder.java  |  18 +
 .../core/query/ServiceInstanceTopologyBuilder.java |  18 +
 .../server/core/query/ServiceTopologyBuilder.java  |  18 +
 .../server/core/query/TopologyQueryService.java    | 149 +++++---
 .../server/core/query/type/EndpointTopology.java   |   4 +
 .../server/core/query/type/ProcessTopology.java    |   6 +-
 .../core/query/type/ServiceInstanceTopology.java   |   4 +
 .../oap/server/core/query/type/Topology.java       |   4 +
 .../core/storage/query/ITopologyQueryDAO.java      | 155 ++++++++
 .../oap/query/debug/DebuggingHTTPHandler.java      | 111 ++++++
 .../debug/DebuggingQueryExceptionHandler.java      |  45 +++
 .../DebuggingQueryEndpointTopologyRsp.java}        |  16 +-
 .../DebuggingQueryInstanceTopologyRsp.java}        |  17 +-
 .../DebuggingQueryProcessTopologyRsp.java}         |  21 +-
 .../DebuggingQueryServiceTopologyRsp.java}         |  16 +-
 .../oap/query/graphql/resolver/TopologyQuery.java  | 133 ++++++-
 .../src/main/resources/query-protocol              |   2 +-
 .../banyandb/measure/BanyanDBTopologyQueryDAO.java |  10 +-
 .../storage/plugin/elasticsearch/base/EsDAO.java   |   4 +
 .../elasticsearch/query/RecordsQueryEsDAO.java     |   2 +-
 .../elasticsearch/query/TopologyQueryEsDAO.java    |   8 +-
 25 files changed, 1086 insertions(+), 179 deletions(-)

diff --git a/docs/en/api/query-protocol.md b/docs/en/api/query-protocol.md
index 346cb839b7..8f5936ea2b 100644
--- a/docs/en/api/query-protocol.md
+++ b/docs/en/api/query-protocol.md
@@ -55,23 +55,24 @@ extend type Query {
 The topology and dependency graphs among services, instances and endpoints. 
Includes direct relationships or global maps.
 
 ```graphql
+# Param, if debug is true will enable the query tracing and return 
DebuggingTrace in the result.
 extend type Query {
     # Query the global topology
     # When layer is specified, the topology of this layer would be queried
-    getGlobalTopology(duration: Duration!, layer: String): Topology
+    getGlobalTopology(duration: Duration!, layer: String, debug: Boolean): 
Topology
     # Query the topology, based on the given service
-    getServiceTopology(serviceId: ID!, duration: Duration!): Topology
+    getServiceTopology(serviceId: ID!, duration: Duration!, debug: Boolean): 
Topology
     # Query the topology, based on the given services.
     # `#getServiceTopology` could be replaced by this.
-    getServicesTopology(serviceIds: [ID!]!, duration: Duration!): Topology
+    getServicesTopology(serviceIds: [ID!]!, duration: Duration!, debug: 
Boolean): Topology
     # Query the instance topology, based on the given clientServiceId and 
serverServiceId
-    getServiceInstanceTopology(clientServiceId: ID!, serverServiceId: ID!, 
duration: Duration!): ServiceInstanceTopology
+    getServiceInstanceTopology(clientServiceId: ID!, serverServiceId: ID!, 
duration: Duration!, debug: Boolean): ServiceInstanceTopology
     # Query the topology, based on the given endpoint
     getEndpointTopology(endpointId: ID!, duration: Duration!): Topology
     # v2 of getEndpointTopology
-    getEndpointDependencies(endpointId: ID!, duration: Duration!): 
EndpointTopology
+    getEndpointDependencies(endpointId: ID!, duration: Duration!, debug: 
Boolean): EndpointTopology
     # Query the topology, based on the given instance
-    getProcessTopology(serviceInstanceId: ID!, duration: Duration!): 
ProcessTopology
+    getProcessTopology(serviceInstanceId: ID!, duration: Duration!, debug: 
Boolean): ProcessTopology
 }
 ```
 
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index dd5f0275d9..82222b25ee 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -27,6 +27,7 @@
 * Support BanyanDB internal metrics query execution tracing.
 * BanyanDB client config: rise the default `maxBulkSize` to 10000, add 
`flushTimeout` and set default to 10s.
 * Polish BanyanDB group and schema creation logic to fix the schema creation 
failure issue in distributed race conditions.
+* Support tracing topology query for debugging.
 
 #### UI
 * Highlight search log keywords.
diff --git a/docs/en/debugging/query-tracing.md 
b/docs/en/debugging/query-tracing.md
index 55668a9f0a..065ec02853 100644
--- a/docs/en/debugging/query-tracing.md
+++ b/docs/en/debugging/query-tracing.md
@@ -15,16 +15,16 @@ SkyWalking OAP provides the metrics/trace/log/topology 
query tracing to help use
 
 - Span
 
-| Field        | Description                                                   
                                                   |
-|--------------|------------------------------------------------------------------------------------------------------------------|
-| spanId       | The unique ID of the span                                     
                                                   |
-| parentSpanId | The parent span ID of the span                                
                                                   |
-| operation    | The operation name of the span                                
                                                   |
-| startTime    | The start time of the span. In nanoseconds                    
                                                   |
-| endTime      | The end time of the span. In nanoseconds                      
                                                   |
-| duration     | The duration of the span. In nanoseconds                      
                                                   |
-| msg          | The message of the span, could include additional info such 
as request condition and response from the Database  |
-| error        | The error message of the span, if the span has an error.      
                                                   |
+| Field        | Description                                                   
                                                                                
     |
+|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
+| spanId       | The unique ID of the span                                     
                                                                                
     |
+| parentSpanId | The parent span ID of the span                                
                                                                                
     |
+| operation    | The operation name of the span                                
                                                                                
     |
+| startTime    | The start time of the span. In nanoseconds, this is a 
relative time based on different env and implementation                         
             |
+| endTime      | The end time of the span. In nanoseconds, this is a relative 
time based on different env and implementation                                  
                                                                       |
+| duration     | The duration of the span. In nanoseconds                      
                                                                                
     |
+| msg          | The message of the span, could include additional info such 
as request condition and response from the Database or Tags from BanyanDB 
internal trace |
+| error        | The error message of the span, if the span has an error.      
                                                                                
     |
 
 
 ## Debugging through HTTP APIs
@@ -57,10 +57,10 @@ The time and step parameters are follow the 
[Duration](../api/query-protocol.md#
 
 - Example
 
-Tracing an avg query with the MQE query expression `avg(service_sla)` from 
2024-06-18 11 to 2024-06-18 12 with the step HOUR for the service 
`mock_a_service` and the service layer `GENERAL`.
+Tracing an avg query with the MQE query expression `avg(service_sla)` from 
2024-07-03 to 2024-07-03 with the step DAY for the service `mock_a_service` and 
the service layer `GENERAL`.
 
 ```shell
-curl -X GET 
'http://127.0.0.1:12800/debugging/query/mqe?dumpDBRsp=true&expression=avg(service_sla)&startTime=2024-06-18%2011&endTime=2024-06-18%2012&step=HOUR&service=mock_a_service&serviceLayer=GENERAL'
+curl -X GET 
'http://127.0.0.1:12800/debugging/query/mqe?dumpDBRsp=true&expression=avg(service_sla)&startTime=2024-07-03&endTime=2024-07-03&step=DAY&service=mock_a_service&serviceLayer=GENERAL'
 ```
 
 Response will include query result and the debuggingTrace information:
@@ -78,55 +78,103 @@ results:
         emptyValue: false
 error: null
 debuggingTrace:
-  traceId: "a50910fe-c966-4249-87f9-e471e55cf92f"
+  traceId: "4f972417-c543-4f7d-a3f1-f5e694cfeb2b"
   condition: "Expression: avg(service_sla), Entity: Entity(scope=null, 
serviceName=mock_a_service,\
     \ normal=true, serviceInstanceName=null, endpointName=null, 
processName=null,\
     \ destServiceName=null, destNormal=null, destServiceInstanceName=null, 
destEndpointName=null,\
-    \ destProcessName=null), Duration: Duration(start=2024-06-18 11, 
end=2024-06-18\
-    \ 12, step=HOUR)"
-  startTime: 61636369350002
-  endTime: 61636374541189
-  duration: 5191187
+    \ destProcessName=null), Duration: Duration(start=2024-07-03, 
end=2024-07-03,\
+    \ step=DAY)"
+  startTime: 115828803080350
+  endTime: 115828877400237
+  duration: 74319887
   rootSpan:
     spanId: 0
     parentSpanId: -1
     operation: "MQE query"
-    startTime: 61636369352761
-    endTime: 61636374539893
-    duration: 5187132
+    startTime: 115828803110686
+    endTime: 115828877396756
+    duration: 74286070
     msg: null
     error: null
     childSpans:
       - spanId: 1
         parentSpanId: 0
         operation: "MQE syntax analysis"
-        startTime: 61636369357437
-        endTime: 61636369443631
-        duration: 86194
+        startTime: 115828803699331
+        endTime: 115828805015745
+        duration: 1316414
         msg: null
         error: null
         childSpans: []
       - spanId: 2
         parentSpanId: 0
         operation: "MQE Aggregation OP: avg(service_sla)"
-        startTime: 61636369458018
-        endTime: 61636374440560
-        duration: 4982542
+        startTime: 115828805052267
+        endTime: 115828876877134
+        duration: 71824867
         msg: null
         error: null
         childSpans:
           - spanId: 3
             parentSpanId: 2
             operation: "MQE Metric OP: service_sla"
-            startTime: 61636369468839
-            endTime: 61636374373771
-            duration: 4904932
+            startTime: 115828805209453
+            endTime: 115828875634953
+            duration: 70425500
             msg: null
             error: null
             childSpans:
 ...
 ```
 
+**Note:** if using the SkyWalking native storage 
[BanyanDB](../setup/backend/storages/banyandb.md), 
+the debuggingTrace will include the BanyanDB internal execution trace info, 
such as:
+```yaml
+...
+childSpans:
+  - spanId: 7
+    parentSpanId: 6
+    operation: "BanyanDB: measure-grpc"
+    startTime: 1720059017222584700
+    endTime: 1720059017223492400
+    duration: 907700
+    msg: "[Tag(key=request, value={\"groups\":[\"measure-default\"], \"\
+                  name\":\"service_sla_day\", 
\"timeRange\":{\"begin\":\"2024-07-02T16:00:00Z\"\
+                  , \"end\":\"2024-07-03T16:00:00Z\"}, 
\"criteria\":{\"condition\"\
+                  :{\"name\":\"entity_id\", \"op\":\"BINARY_OP_EQ\", 
\"value\":{\"\
+                  str\":{\"value\":\"bW9ja19hX3NlcnZpY2U=.1\"}}}}, 
\"tagProjection\"\
+                  :{\"tagFamilies\":[{\"name\":\"storage-only\", 
\"tags\":[\"entity_id\"\
+                  ]}]}, \"fieldProjection\":{\"names\":[\"percentage\"]}, 
\"trace\"\
+                  :true})]"
+    error: null
+    childSpans:
+      - spanId: 8
+        parentSpanId: 7
+        operation: "BanyanDB: data-0ebf3a27de83:17912"
+        startTime: 1720059017222821600
+        endTime: 1720059017223473500
+        duration: 651900
+        msg: "[Tag(key=plan, value=IndexScan: 
startTime=1719936000,endTime=1720022400,Metadata{group=measure-default,name=service_sla_day},conditions=%!s(<nil>);\
+                    \ projection=#storage-only:entity_id<TAG_TYPE_STRING>; 
order=OrderBy:\
+                    \ [], sort=SORT_UNSPECIFIED; limit=100 Limit: 0, 100)]"
+        error: null
+        childSpans:
+          - spanId: 9
+            parentSpanId: 8
+            operation: "BanyanDB: indexScan-group:\"measure-default\"  name:\"\
+                      service_sla_day\""
+            startTime: 1720059017222879200
+            endTime: 1720059017223293300
+            duration: 414100
+            msg: "[Tag(key=orderBy, value=time SORT_UNSPECIFIED), 
Tag(key=details,\
+                      \ value=IndexScan: 
startTime=1719936000,endTime=1720022400,Metadata{group=measure-default,name=service_sla_day},conditions=%!s(<nil>);\
+                      \ projection=#storage-only:entity_id<TAG_TYPE_STRING>; 
order=OrderBy:\
+                      \ [], sort=SORT_UNSPECIFIED; limit=100)]"
+            error: null
+            childSpans:
+...
+```
+
 ### Tracing SkyWalking Trace Query
 
 #### Tracing SkyWalking API queryBasicTraces
@@ -245,6 +293,153 @@ debuggingTrace:
 ...
 ```
 
+### Tracing Topology Query
+
+#### Tracing SkyWalking API getGlobalTopology
+- URL: HTTP GET `http://{core restHost}:{core 
restPort}/debugging/query/topology/getGlobalTopology?{parameters}`.
+- Parameters
+
+  | Field             | Description                                            
       | Required |
+  
|-------------------|---------------------------------------------------------------|----------|
+  | startTime         | The start time of the query                            
       | Yes      |               
+  | endTime           | The end time of the query                              
       | Yes      |               
+  | step              | The query step                                         
       | Yes      |               
+  | serviceLayer      | The service layer name                                 
       | No       |
+
+- Example
+```shell
+curl -X GET 
'http://127.0.0.1:12800/debugging/query/topology/getGlobalTopology?startTime=2024-07-03&endTime=2024-07-03&step=DAY&serviceLayer=GENERAL'
+```
+
+Response will include query result and the debuggingTrace information, the 
debuggingTrace information is the same as the MQE query tracing:
+
+```yaml
+nodes:
+...
+calls:
+...
+debuggingTrace:
+...
+```
+
+#### Tracing SkyWalking API getServicesTopology
+- URL: HTTP GET `http://{core restHost}:{core 
restPort}/debugging/query/topology/getServicesTopology?{parameters}`.
+- Parameters
+
+  | Field        | Description                                                 
                | Required |
+  
|--------------|-----------------------------------------------------------------------------|----------|
+  | startTime    | The start time of the query                                 
                | Yes      |               
+  | endTime      | The end time of the query                                   
                | Yes      |               
+  | step         | The query step                                              
                | Yes      |               
+  | serviceLayer | The service layer name                                      
                | Yes      |
+  | services     | The services names list, separate by comma `mock_a_service, 
mock_b_service` | Yes      |
+
+- Example
+```shell
+curl -X GET 
'http://127.0.0.1:12800/debugging/query/topology/getServicesTopology?startTime=2024-07-03&endTime=2024-07-03&step=DAY&serviceLayer=GENERAL&services=mock_a_service%2Cmock_b_service'
+```
+
+Response will include query result and the debuggingTrace information, the 
debuggingTrace information is the same as the MQE query tracing:
+
+```yaml
+nodes:
+...
+calls:
+...
+debuggingTrace:
+...
+```
+
+#### Tracing SkyWalking API getServiceInstanceTopology
+- URL: HTTP GET `http://{core restHost}:{core 
restPort}/debugging/query/topology/getServiceInstanceTopology?{parameters}`.
+- Parameters
+
+  | Field              | Description                        | Required |
+  |--------------------|------------------------------------|----------|
+  | startTime          | The start time of the query        | Yes      |       
        
+  | endTime            | The end time of the query          | Yes      |       
        
+  | step               | The query step                     | Yes      |       
        
+  | clientService      | The client side service name       | Yes      |
+  | serverService      | The server side service name       | Yes      |
+  | clientServiceLayer | The client side service layer name | Yes      |
+  | serverServiceLayer | The server side service layer name | Yes      |
+
+- Example
+```shell
+curl -X GET 
'http://127.0.0.1:12800/debugging/query/topology/getServiceInstanceTopology?startTime=2024-07-03&endTime=2024-07-03&step=DAY&clientService=mock_a_service&serverService=mock_b_service&clientServiceLayer=GENERAL&serverServiceLayer=GENERAL'
+```
+
+Response will include query result and the debuggingTrace information, the 
debuggingTrace information is the same as the MQE query tracing:
+
+```yaml
+nodes:
+...
+calls:
+...
+debuggingTrace:
+...
+```
+
+#### Tracing SkyWalking API getEndpointDependencies
+- URL: HTTP GET `http://{core restHost}:{core 
restPort}/debugging/query/topology/getEndpointDependencies?{parameters}`.
+- Parameters
+
+  | Field        | Description                                                 
                | Required |
+  
|--------------|-----------------------------------------------------------------------------|----------|
+  | startTime    | The start time of the query                                 
                | Yes      |               
+  | endTime      | The end time of the query                                   
                | Yes      |               
+  | step         | The query step                                              
                | Yes      |   
+  | service      | The service name                                            
                | Yes      |
+  | serviceLayer | The service layer name                                      
                | Yes      |
+  | endpoint     | The endpoint name                                           
                | Yes      |
+
+- Example
+- Example
+```shell
+curl -X GET 
'http://127.0.0.1:12800/debugging/query/topology/getEndpointDependencies?startTime=2024-07-03&endTime=2024-07-03&step=DAY&service=mock_a_service&serviceLayer=GENERAL&endpoint=%2Fdubbox-case%2Fcase%2Fdubbox-rest%2F404-test'
+```
+
+Response will include query result and the debuggingTrace information, the 
debuggingTrace information is the same as the MQE query tracing:
+
+```yaml
+nodes:
+...
+calls:
+...
+debuggingTrace:
+...
+```
+
+#### Tracing SkyWalking API getProcessTopology
+- URL: HTTP GET `http://{core restHost}:{core 
restPort}/debugging/query/topology/getProcessTopology?{parameters}`.
+- Parameters
+
+  | Field         | Description                                                
                 | Required |
+  
|---------------|-----------------------------------------------------------------------------|----------|
+  | startTime     | The start time of the query                                
                 | Yes      |               
+  | endTime       | The end time of the query                                  
                 | Yes      |               
+  | step          | The query step                                             
                 | Yes      |   
+  | service       | The service name                                           
                 | Yes      |
+  | serviceLayer  | The service layer name                                     
                 | Yes      |
+  | instance      | The instance name                                          
                 | Yes      |
+
+- Example
+```shell
+
+curl -X GET 
'http://127.0.0.1:12800/debugging/query/topology/getProcessTopology?startTime=2024-07-03&endTime=2024-07-03&step=DAY&service=mock_a_service&serviceLayer=GENERAL&instance=mock_a_service_instance'
+```
+
+Response will include query result and the debuggingTrace information, the 
debuggingTrace information is the same as the MQE query tracing:
+
+```yaml
+nodes:
+...
+calls:
+...
+debuggingTrace:
+...
+```
+
 ## Debugging with GraphQL bundled
 When querying the metrics though the [GraphQL APIs](../api/query-protocol.md),
 the query tracing service is also provided within the GraphQL bundled.
@@ -277,7 +472,7 @@ http://127.0.0.1:12800/graphql
 
 ```graphql
 {
-    execExpression(expression: "avg(service_sla)", entity: {serviceName: 
"mock_a_service", normal: true}, duration: {start: "2024-06-18 11", end: 
"2024-06-18 12", step: HOUR}, debug: true, dumpDBRsp: true) {
+    execExpression(expression: "avg(service_sla)", entity: {serviceName: 
"mock_a_service", normal: true}, duration: {start: "2024-07-03", end: 
"2024-07-03", step: DAY}, debug: true, dumpDBRsp: true) {
         type
         error
         results {
@@ -338,19 +533,19 @@ Response will include query result and the execTrace 
information:
         }
       ],
       "debuggingTrace": {
-        "traceId": "7caa6529-9a72-4878-ab82-7a9ca032a97b",
-        "condition": "Expression: avg(service_sla), Entity: Entity(scope=null, 
serviceName=mock_a_service, normal=true, serviceInstanceName=null, 
endpointName=null, processName=null, destServiceName=null, destNormal=null, 
destServiceInstanceName=null, destEndpointName=null, destProcessName=null), 
Duration: Duration(start=2024-06-18 11, end=2024-06-18 12, step=HOUR)",
-        "startTime": 73040673584523,
-        "endTime": 73040678525541,
-        "duration": 4941018,
+        "traceId": "3116ffe3-ee9c-4047-9f22-c135c237aad5",
+        "condition": "Expression: avg(service_sla), Entity: Entity(scope=null, 
serviceName=mock_a_service, normal=true, serviceInstanceName=null, 
endpointName=null, processName=null, destServiceName=null, destNormal=null, 
destServiceInstanceName=null, destEndpointName=null, destProcessName=null), 
Duration: Duration(start=2024-07-03, end=2024-07-03, step=DAY)",
+        "startTime": 117259274324665,
+        "endTime": 117259279847720,
+        "duration": 5523055,
         "spans": [
           {
             "spanId": 0,
             "parentSpanId": -1,
             "operation": "MQE query",
-            "startTime": 73040673586770,
-            "endTime": 73040678523624,
-            "duration": 4936854,
+            "startTime": 117259274328719,
+            "endTime": 117259279846559,
+            "duration": 5517840,
             "msg": null,
             "error": null
           },
@@ -358,9 +553,9 @@ Response will include query result and the execTrace 
information:
             "spanId": 1,
             "parentSpanId": 0,
             "operation": "MQE syntax analysis",
-            "startTime": 73040673591566,
-            "endTime": 73040673677579,
-            "duration": 86013,
+            "startTime": 117259274333084,
+            "endTime": 117259274420159,
+            "duration": 87075,
             "msg": null,
             "error": null
           },
@@ -368,9 +563,9 @@ Response will include query result and the execTrace 
information:
             "spanId": 2,
             "parentSpanId": 0,
             "operation": "MQE Aggregation OP: avg(service_sla)",
-            "startTime": 73040673691700,
-            "endTime": 73040678270159,
-            "duration": 4578459,
+            "startTime": 117259274433533,
+            "endTime": 117259279812549,
+            "duration": 5379016,
             "msg": null,
             "error": null
           },
@@ -381,6 +576,53 @@ Response will include query result and the execTrace 
information:
   }
 }
 ```
+**Note:** if using the SkyWalking native storage 
[BanyanDB](../setup/backend/storages/banyandb.md),
+the debuggingTrace will include the BanyanDB internal execution trace info, 
such as:
+```json
+...
+{
+  "spanId": 7,
+  "parentSpanId": 6,
+  "operation": "BanyanDB: measure-grpc",
+  "startTime": 1720060447687765300,
+  "endTime": 1720060447688830200,
+  "duration": 1064900,
+  "msg": "[Tag(key=request, value={\"groups\":[\"measure-default\"], 
\"name\":\"service_sla_day\", 
\"timeRange\":{\"begin\":\"2024-07-02T16:00:00Z\", 
\"end\":\"2024-07-03T16:00:00Z\"}, 
\"criteria\":{\"condition\":{\"name\":\"entity_id\", \"op\":\"BINARY_OP_EQ\", 
\"value\":{\"str\":{\"value\":\"bW9ja19hX3NlcnZpY2U=.1\"}}}}, 
\"tagProjection\":{\"tagFamilies\":[{\"name\":\"storage-only\", 
\"tags\":[\"entity_id\"]}]}, \"fieldProjection\":{\"names\":[\"percentage\"]}, 
\"trace\":true})]",
+  "error": null
+},
+{
+"spanId": 8,
+"parentSpanId": 7,
+"operation": "BanyanDB: data-0ebf3a27de83:17912",
+"startTime": 1720060447687956700,
+"endTime": 1720060447688810000,
+"duration": 853300,
+"msg": "[Tag(key=plan, value=IndexScan: 
startTime=1719936000,endTime=1720022400,Metadata{group=measure-default,name=service_sla_day},conditions=%!s(<nil>);
 projection=#storage-only:entity_id<TAG_TYPE_STRING>; order=OrderBy: [], 
sort=SORT_UNSPECIFIED; limit=100 Limit: 0, 100)]",
+"error": null
+},
+{
+"spanId": 9,
+"parentSpanId": 8,
+"operation": "BanyanDB: indexScan-group:\"measure-default\"  
name:\"service_sla_day\"",
+"startTime": 1720060447687997400,
+"endTime": 1720060447688664700,
+"duration": 667300,
+"msg": "[Tag(key=orderBy, value=time SORT_UNSPECIFIED), Tag(key=details, 
value=IndexScan: 
startTime=1719936000,endTime=1720022400,Metadata{group=measure-default,name=service_sla_day},conditions=%!s(<nil>);
 projection=#storage-only:entity_id<TAG_TYPE_STRING>; order=OrderBy: [], 
sort=SORT_UNSPECIFIED; limit=100)]",
+"error": null
+},
+{
+"spanId": 10,
+"parentSpanId": 9,
+"operation": "BanyanDB: seriesIndex.Search",
+"startTime": 1720060447688023800,
+"endTime": 1720060447688101800,
+"duration": 78000,
+"msg": "[]",
+"error": null
+},
+...
+```
+
 ### Tracing SkyWalking Trace Query
 
 #### Tracing SkyWalking API queryBasicTraces
@@ -389,8 +631,10 @@ Response will include query result and the execTrace 
information:
 ```graphql
 # Param, if debug is true will enable the query tracing and return 
DebuggingTrace in the result.
 extend type Query {
-    # Search segment list with given conditions
-    queryBasicTraces(condition: TraceQueryCondition, debug: Boolean): 
TraceBrief
+  # Search segment list with given conditions
+  queryBasicTraces(condition: TraceQueryCondition, debug: Boolean): TraceBrief
+  # Read the specific trace ID with given trace ID
+  queryTrace(traceId: ID!, debug: Boolean): Trace
 ...
 }
 ```
@@ -402,35 +646,74 @@ type TraceBrief {
     #For OAP internal query debugging
     debuggingTrace: DebuggingTrace
 }
+
+# The trace represents a distributed trace, includes all segments and spans.
+type Trace {
+...
+    #For OAP internal query debugging
+    debuggingTrace: DebuggingTrace
+}
 ```
 
 - Example
 
-Same as the MQE query tracing, follow the GraphQL protocol and grammar to 
query the result and get debuggingTrace information, 
+Same as the MQE query tracing, follow the GraphQL protocol and grammar to 
query the result and get debuggingTrace information,
 just enable the debug parameter to true.
 
-#### Tracing SkyWalking API queryTrace
-- Bundle API: [Trace](../api/query-protocol.md#trace)
+### Tracing Topology Query
+- Bundle API: [Topology](../api/query-protocol.md#topology)
 
-```graphql  
+```graphql
 # Param, if debug is true will enable the query tracing and return 
DebuggingTrace in the result.
 extend type Query {
-    # Read the specific trace ID with given trace ID
-    queryTrace(traceId: ID!, debug: Boolean): Trace
-    ...
+    # Query the global topology
+    # When layer is specified, the topology of this layer would be queried
+    getGlobalTopology(duration: Duration!, layer: String, debug: Boolean): 
Topology
+    # Query the topology, based on the given service
+    getServiceTopology(serviceId: ID!, duration: Duration!, debug: Boolean): 
Topology
+    # Query the topology, based on the given services.
+    # `#getServiceTopology` could be replaced by this.
+    getServicesTopology(serviceIds: [ID!]!, duration: Duration!, debug: 
Boolean): Topology
+    # Query the instance topology, based on the given clientServiceId and 
serverServiceId
+    getServiceInstanceTopology(clientServiceId: ID!, serverServiceId: ID!, 
duration: Duration!, debug: Boolean): ServiceInstanceTopology
+...
+    # v2 of getEndpointTopology
+    getEndpointDependencies(endpointId: ID!, duration: Duration!, debug: 
Boolean): EndpointTopology
+    # Query the topology, based on the given instance
+    getProcessTopology(serviceInstanceId: ID!, duration: Duration!, debug: 
Boolean): ProcessTopology
 }
 ```
 
 ```graphql
-# The trace represents a distributed trace, includes all segments and spans.
-type Trace {
-...
-    #For OAP internal query debugging
-    debuggingTrace: DebuggingTrace
+# The overview topology of the whole application cluster or services,
+type Topology {
+  nodes: [Node!]!
+  calls: [Call!]!
+  debuggingTrace: DebuggingTrace
+}
+
+# The instance topology based on the given serviceIds
+type ServiceInstanceTopology {
+  nodes: [ServiceInstanceNode!]!
+  calls: [Call!]!
+  debuggingTrace: DebuggingTrace
+}
+
+# The endpoint topology
+type EndpointTopology {
+  nodes: [EndpointNode!]!
+  calls: [Call!]!
+  debuggingTrace: DebuggingTrace
+}
+
+# The process topology
+type ProcessTopology {
+  nodes: [ProcessNode!]!
+  calls: [Call!]!
+  debuggingTrace: DebuggingTrace
 }
 ```
 
 - Example
-
 Same as the MQE query tracing, follow the GraphQL protocol and grammar to 
query the result and get debuggingTrace information,
 just enable the debug parameter to true.
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EndpointTopologyBuilder.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EndpointTopologyBuilder.java
new file mode 100644
index 0000000000..dc391ca023
--- /dev/null
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EndpointTopologyBuilder.java
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.EndpointNode;
+import org.apache.skywalking.oap.server.core.query.type.EndpointTopology;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
+import org.apache.skywalking.oap.server.core.source.DetectPoint;
+
+public class EndpointTopologyBuilder {
+
+    EndpointTopology buildDebuggable(List<Call.CallDetail> serverSideCalls) {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Build endpoint topology");
+            }
+            return build(serverSideCalls);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    EndpointTopology build(List<Call.CallDetail> serverSideCalls) {
+        EndpointTopology topology = new EndpointTopology();
+        serverSideCalls.forEach(callDetail -> {
+            Call call = new Call();
+            call.setId(callDetail.getId());
+            call.setSource(callDetail.getSource());
+            call.setTarget(callDetail.getTarget());
+            call.addDetectPoint(DetectPoint.SERVER);
+            topology.getCalls().add(call);
+        });
+
+        Set<String> nodeIds = new HashSet<>();
+        serverSideCalls.forEach(call -> {
+            if (!nodeIds.contains(call.getSource())) {
+                
topology.getNodes().add(buildEndpointDependencyNode(call.getSource()));
+                nodeIds.add(call.getSource());
+            }
+            if (!nodeIds.contains(call.getTarget())) {
+                
topology.getNodes().add(buildEndpointDependencyNode(call.getTarget()));
+                nodeIds.add(call.getTarget());
+            }
+        });
+        return topology;
+    }
+
+    private EndpointNode buildEndpointDependencyNode(String endpointId) {
+        final IDManager.EndpointID.EndpointIDDefinition endpointIDDefinition = 
IDManager.EndpointID.analysisId(
+            endpointId);
+        EndpointNode instanceNode = new EndpointNode();
+        instanceNode.setId(endpointId);
+        instanceNode.setName(endpointIDDefinition.getEndpointName());
+        instanceNode.setServiceId(endpointIDDefinition.getServiceId());
+        final IDManager.ServiceID.ServiceIDDefinition serviceIDDefinition = 
IDManager.ServiceID.analysisId(
+            endpointIDDefinition.getServiceId());
+        instanceNode.setServiceName(serviceIDDefinition.getName());
+        instanceNode.setReal(serviceIDDefinition.isReal());
+        return instanceNode;
+    }
+}
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProcessTopologyBuilder.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProcessTopologyBuilder.java
index 1b79dcd24a..8cdf6e0cdc 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProcessTopologyBuilder.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProcessTopologyBuilder.java
@@ -27,6 +27,8 @@ import 
org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogServ
 import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.core.query.type.ProcessNode;
 import org.apache.skywalking.oap.server.core.query.type.ProcessTopology;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.core.storage.IMetricsDAO;
 import org.apache.skywalking.oap.server.core.storage.StorageDAO;
@@ -68,6 +70,22 @@ public class ProcessTopologyBuilder {
             .getService(IComponentLibraryCatalogService.class);
     }
 
+    ProcessTopology buildDebuggable(List<Call.CallDetail> clientCalls,
+                                    List<Call.CallDetail> serverCalls) throws 
Exception {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Build process topology");
+            }
+            return build(clientCalls, serverCalls);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
     ProcessTopology build(List<Call.CallDetail> clientCalls,
                           List<Call.CallDetail> serverCalls) throws Exception {
         log.debug("building process topology, total found client calls: {}, 
total found server calls: {}",
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
index bf8ae8f6c3..3466c7d327 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceInstanceTopologyBuilder.java
@@ -28,6 +28,8 @@ import 
org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.core.query.type.ServiceInstanceNode;
 import 
org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
@@ -37,6 +39,22 @@ public class ServiceInstanceTopologyBuilder {
     public ServiceInstanceTopologyBuilder(ModuleManager moduleManager) {
     }
 
+    ServiceInstanceTopology buildDebuggable(List<Call.CallDetail> 
serviceInstanceRelationClientCalls,
+                                  List<Call.CallDetail> 
serviceInstanceRelationServerCalls) {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Build service instance 
topology");
+            }
+            return build(serviceInstanceRelationClientCalls, 
serviceInstanceRelationServerCalls);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
     ServiceInstanceTopology build(List<Call.CallDetail> 
serviceInstanceRelationClientCalls,
                                   List<Call.CallDetail> 
serviceInstanceRelationServerCalls) {
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
index ba48400f74..e953d7c6c3 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ServiceTopologyBuilder.java
@@ -35,6 +35,8 @@ import org.apache.skywalking.oap.server.core.query.type.Call;
 import org.apache.skywalking.oap.server.core.query.type.Node;
 import org.apache.skywalking.oap.server.core.query.type.Service;
 import org.apache.skywalking.oap.server.core.query.type.Topology;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.util.StringUtil;
@@ -67,6 +69,22 @@ class ServiceTopologyBuilder {
         return metadataQueryService;
     }
 
+    Topology buildDebuggable(List<Call.CallDetail> serviceRelationClientCalls,
+                             List<Call.CallDetail> serviceRelationServerCalls) 
{
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Build service topology");
+            }
+            return build(serviceRelationClientCalls, 
serviceRelationServerCalls);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
     Topology build(List<Call.CallDetail> serviceRelationClientCalls, 
List<Call.CallDetail> serviceRelationServerCalls) {
 
         Map<String, Node> nodes = new HashMap<>();
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
index 449428f434..f4a37f5177 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TopologyQueryService.java
@@ -26,12 +26,13 @@ import 
org.apache.skywalking.oap.server.core.analysis.IDManager;
 import 
org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
 import org.apache.skywalking.oap.server.core.query.type.Call;
-import org.apache.skywalking.oap.server.core.query.type.EndpointNode;
 import org.apache.skywalking.oap.server.core.query.type.EndpointTopology;
 import org.apache.skywalking.oap.server.core.query.type.Node;
 import org.apache.skywalking.oap.server.core.query.type.ProcessTopology;
 import 
org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
 import org.apache.skywalking.oap.server.core.query.type.Topology;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
 import org.apache.skywalking.oap.server.core.source.DetectPoint;
 import org.apache.skywalking.oap.server.core.storage.StorageModule;
 import org.apache.skywalking.oap.server.core.storage.model.StorageModels;
@@ -50,6 +51,8 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import static 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext.TRACE_CONTEXT;
+
 @Slf4j
 public class TopologyQueryService implements Service {
     private final ModuleManager moduleManager;
@@ -87,30 +90,63 @@ public class TopologyQueryService implements Service {
     }
 
     public Topology getGlobalTopology(final Duration duration, final String 
layer) throws IOException {
+        DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Service: 
getGlobalTopology");
+                span.setMsg("Duration: " + duration + ", Layer: " + layer);
+            }
+            return invokeGetGlobalTopology(duration, layer);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    private Topology invokeGetGlobalTopology(final Duration duration, final 
String layer) throws IOException {
         if (StringUtil.isNotEmpty(layer)) {
             final List<String> serviceIdList = 
Optional.ofNullable(getMetadataQueryService().listServices(layer, null))
                 .map(list -> list.stream().map(s -> 
s.getId()).collect(Collectors.toList()))
                 .orElse(Collections.emptyList());
             return getServiceTopology(duration, serviceIdList);
         }
-        List<Call.CallDetail> serviceRelationServerCalls = 
getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSide(
+        List<Call.CallDetail> serviceRelationServerCalls = 
getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSideDebuggable(
             duration);
-        List<Call.CallDetail> serviceRelationClientCalls = 
getTopologyQueryDAO().loadServiceRelationDetectedAtClientSide(
+        List<Call.CallDetail> serviceRelationClientCalls = 
getTopologyQueryDAO().loadServiceRelationDetectedAtClientSideDebuggable(
             duration);
 
         ServiceTopologyBuilder builder = new 
ServiceTopologyBuilder(moduleManager);
-        return builder.build(serviceRelationClientCalls, 
serviceRelationServerCalls);
+        return builder.buildDebuggable(serviceRelationClientCalls, 
serviceRelationServerCalls);
     }
 
     public Topology getServiceTopology(final Duration duration,
+                                              final List<String> serviceIds) 
throws IOException {
+        DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Service: 
getServiceTopology");
+                span.setMsg("Duration: " + duration + ", ServiceIds: " + 
serviceIds);
+            }
+            return invokeGetServiceTopology(duration, serviceIds);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    private Topology invokeGetServiceTopology(final Duration duration,
                                        final List<String> serviceIds) throws 
IOException {
-        List<Call.CallDetail> serviceRelationClientCalls = 
getTopologyQueryDAO().loadServiceRelationDetectedAtClientSide(
+        List<Call.CallDetail> serviceRelationClientCalls = 
getTopologyQueryDAO().loadServiceRelationDetectedAtClientSideDebuggable(
             duration, serviceIds);
-        List<Call.CallDetail> serviceRelationServerCalls = 
getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSide(
+        List<Call.CallDetail> serviceRelationServerCalls = 
getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSideDebuggable(
             duration, serviceIds);
 
         ServiceTopologyBuilder builder = new 
ServiceTopologyBuilder(moduleManager);
-        Topology topology = builder.build(serviceRelationClientCalls, 
serviceRelationServerCalls);
+        Topology topology = 
builder.buildDebuggable(serviceRelationClientCalls, serviceRelationServerCalls);
 
         /**
          * The topology built above is complete.
@@ -127,7 +163,7 @@ public class TopologyQueryService implements Service {
         });
         if (CollectionUtils.isNotEmpty(outScopeSourceServiceIds)) {
             // If exist, query them as the server side to get the target's 
component.
-            List<Call.CallDetail> sourceCalls = 
getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSide(
+            List<Call.CallDetail> sourceCalls = 
getTopologyQueryDAO().loadServiceRelationsDetectedAtServerSideDebuggable(
                 duration, outScopeSourceServiceIds);
             topology.getNodes().forEach(node -> {
                 if (Strings.isNullOrEmpty(node.getType())) {
@@ -147,9 +183,27 @@ public class TopologyQueryService implements Service {
     public ServiceInstanceTopology getServiceInstanceTopology(final String 
clientServiceId,
                                                               final String 
serverServiceId,
                                                               final Duration 
duration) throws IOException {
-        List<Call.CallDetail> serviceInstanceRelationClientCalls = 
getTopologyQueryDAO().loadInstanceRelationDetectedAtClientSide(
+        DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Service: 
getServiceInstanceTopology");
+                span.setMsg("ClientServiceId: " + clientServiceId + ", 
ServerServiceId: " + serverServiceId + ", Duration: " + duration);
+            }
+            return invokeGetServiceInstanceTopology(clientServiceId, 
serverServiceId, duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    private ServiceInstanceTopology invokeGetServiceInstanceTopology(final 
String clientServiceId,
+                                                              final String 
serverServiceId,
+                                                              final Duration 
duration) throws IOException {
+        List<Call.CallDetail> serviceInstanceRelationClientCalls = 
getTopologyQueryDAO().loadInstanceRelationDetectedAtClientSideDebuggable(
             clientServiceId, serverServiceId, duration);
-        List<Call.CallDetail> serviceInstanceRelationServerCalls = 
getTopologyQueryDAO().loadInstanceRelationDetectedAtServerSide(
+        List<Call.CallDetail> serviceInstanceRelationServerCalls = 
getTopologyQueryDAO().loadInstanceRelationDetectedAtServerSideDebuggable(
             clientServiceId, serverServiceId, duration);
 
         ServiceInstanceTopologyBuilder builder = new 
ServiceInstanceTopologyBuilder(moduleManager);
@@ -189,37 +243,48 @@ public class TopologyQueryService implements Service {
 
     public EndpointTopology getEndpointDependencies(final Duration duration,
                                                     final String endpointId) 
throws IOException {
-        List<Call.CallDetail> serverSideCalls = 
getTopologyQueryDAO().loadEndpointRelation(
-            duration, endpointId);
-
-        EndpointTopology topology = new EndpointTopology();
-        serverSideCalls.forEach(callDetail -> {
-            Call call = new Call();
-            call.setId(callDetail.getId());
-            call.setSource(callDetail.getSource());
-            call.setTarget(callDetail.getTarget());
-            call.addDetectPoint(DetectPoint.SERVER);
-            topology.getCalls().add(call);
-        });
-
-        Set<String> nodeIds = new HashSet<>();
-        serverSideCalls.forEach(call -> {
-            if (!nodeIds.contains(call.getSource())) {
-                
topology.getNodes().add(buildEndpointDependencyNode(call.getSource()));
-                nodeIds.add(call.getSource());
+        DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Service: 
getEndpointDependencies");
+                span.setMsg("Duration: " + duration + ", EndpointId: " + 
endpointId);
             }
-            if (!nodeIds.contains(call.getTarget())) {
-                
topology.getNodes().add(buildEndpointDependencyNode(call.getTarget()));
-                nodeIds.add(call.getTarget());
+            return invokeGetEndpointDependencies(duration, endpointId);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
             }
-        });
+        }
+    }
 
-        return topology;
+    private EndpointTopology invokeGetEndpointDependencies(final Duration 
duration,
+                                                    final String endpointId) 
throws IOException {
+        List<Call.CallDetail> serverSideCalls = 
getTopologyQueryDAO().loadEndpointRelationDebuggable(
+            duration, endpointId);
+        EndpointTopologyBuilder builder = new EndpointTopologyBuilder();
+        return builder.build(serverSideCalls);
     }
 
     public ProcessTopology getProcessTopology(final String instanceId, final 
Duration duration) throws Exception {
-        final List<Call.CallDetail> clientCalls = 
getTopologyQueryDAO().loadProcessRelationDetectedAtClientSide(instanceId, 
duration);
-        final List<Call.CallDetail> serverCalls = 
getTopologyQueryDAO().loadProcessRelationDetectedAtServerSide(instanceId, 
duration);
+        DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Service: 
getProcessTopology");
+                span.setMsg("InstanceId: " + instanceId + ", Duration: " + 
duration);
+            }
+            return invokeGetProcessTopology(instanceId, duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    private ProcessTopology invokeGetProcessTopology(final String instanceId, 
final Duration duration) throws Exception {
+        final List<Call.CallDetail> clientCalls = 
getTopologyQueryDAO().loadProcessRelationDetectedAtClientSideDebuggable(instanceId,
 duration);
+        final List<Call.CallDetail> serverCalls = 
getTopologyQueryDAO().loadProcessRelationDetectedAtServerSideDebuggable(instanceId,
 duration);
 
         final ProcessTopologyBuilder topologyBuilder = new 
ProcessTopologyBuilder(moduleManager, storageModels);
         return topologyBuilder.build(clientCalls, serverCalls);
@@ -236,18 +301,4 @@ public class TopologyQueryService implements Service {
         node.setReal(true);
         return node;
     }
-
-    private EndpointNode buildEndpointDependencyNode(String endpointId) {
-        final IDManager.EndpointID.EndpointIDDefinition endpointIDDefinition = 
IDManager.EndpointID.analysisId(
-            endpointId);
-        EndpointNode instanceNode = new EndpointNode();
-        instanceNode.setId(endpointId);
-        instanceNode.setName(endpointIDDefinition.getEndpointName());
-        instanceNode.setServiceId(endpointIDDefinition.getServiceId());
-        final IDManager.ServiceID.ServiceIDDefinition serviceIDDefinition = 
IDManager.ServiceID.analysisId(
-            endpointIDDefinition.getServiceId());
-        instanceNode.setServiceName(serviceIDDefinition.getName());
-        instanceNode.setReal(serviceIDDefinition.isReal());
-        return instanceNode;
-    }
 }
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
index 2510d9117f..4267c7596f 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
@@ -21,11 +21,15 @@ package org.apache.skywalking.oap.server.core.query.type;
 import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
 
 @Getter
 public class EndpointTopology {
     private final List<EndpointNode> nodes;
     private final List<Call> calls;
+    @Setter
+    private DebuggingTrace debuggingTrace;
 
     public EndpointTopology() {
         this.nodes = new ArrayList<>();
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
index 79518aa05e..1ae63b9371 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
@@ -22,14 +22,18 @@ import lombok.Getter;
 
 import java.util.ArrayList;
 import java.util.List;
+import lombok.Setter;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
 
 @Getter
 public class ProcessTopology {
     private final List<ProcessNode> nodes;
     private final List<Call> calls;
+    @Setter
+    private DebuggingTrace debuggingTrace;
 
     public ProcessTopology() {
         this.nodes = new ArrayList<>();
         this.calls = new ArrayList<>();
     }
-}
\ No newline at end of file
+}
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
index 30070d1335..2b38bd95b7 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
@@ -21,12 +21,16 @@ package org.apache.skywalking.oap.server.core.query.type;
 import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
 
 @Getter
 public class ServiceInstanceTopology {
 
     private final List<ServiceInstanceNode> nodes;
     private final List<Call> calls;
+    @Setter
+    private DebuggingTrace debuggingTrace;
 
     public ServiceInstanceTopology() {
         this.nodes = new ArrayList<>();
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
index 7b571157db..274cb8dfb6 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
@@ -21,11 +21,15 @@ package org.apache.skywalking.oap.server.core.query.type;
 import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTrace;
 
 @Getter
 public class Topology {
     private final List<Node> nodes;
     private final List<Call> calls;
+    @Setter
+    private DebuggingTrace debuggingTrace;
 
     public Topology() {
         this.nodes = new ArrayList<>();
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
index 2415911283..f55d10c5a0 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITopologyQueryDAO.java
@@ -26,9 +26,164 @@ import 
org.apache.skywalking.oap.server.core.analysis.manual.relation.service.Se
 import 
org.apache.skywalking.oap.server.core.analysis.manual.relation.service.ServiceRelationServerSideMetrics;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
 import org.apache.skywalking.oap.server.core.query.type.Call;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
 import org.apache.skywalking.oap.server.library.module.Service;
 
 public interface ITopologyQueryDAO extends Service {
+    default List<Call.CallDetail> 
loadServiceRelationsDetectedAtServerSideDebuggable(Duration duration) throws 
IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadServiceRelationsDetectedAtServerSide");
+                span.setMsg("Duration: " + duration);
+            }
+            return loadServiceRelationsDetectedAtServerSide(duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadServiceRelationDetectedAtClientSideDebuggable(Duration duration) throws 
IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadServiceRelationDetectedAtClientSide");
+                span.setMsg("Duration: " + duration);
+            }
+            return loadServiceRelationDetectedAtClientSide(duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadServiceRelationsDetectedAtServerSideDebuggable(Duration duration,
+                                                                               
List<String> serviceIds) throws IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadServiceRelationsDetectedAtServerSide");
+                span.setMsg("Duration: " + duration + ", ServiceIds: " + 
serviceIds);
+            }
+            return loadServiceRelationsDetectedAtServerSide(duration, 
serviceIds);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadServiceRelationDetectedAtClientSideDebuggable(Duration duration,
+                                                                              
List<String> serviceIds) throws IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadServiceRelationDetectedAtClientSide");
+                span.setMsg("Duration: " + duration + ", ServiceIds: " + 
serviceIds);
+            }
+            return loadServiceRelationDetectedAtClientSide(duration, 
serviceIds);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadInstanceRelationDetectedAtServerSideDebuggable(String clientServiceId,
+                                                                               
String serverServiceId,
+                                                                               
Duration duration) throws IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadInstanceRelationDetectedAtServerSide");
+                span.setMsg("ClientServiceId: " + clientServiceId + ", 
ServerServiceId: " + serverServiceId + ", Duration: " + duration);
+            }
+            return loadInstanceRelationDetectedAtServerSide(clientServiceId, 
serverServiceId, duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadInstanceRelationDetectedAtClientSideDebuggable(String clientServiceId,
+                                                                               
String serverServiceId,
+                                                                               
Duration duration) throws IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadInstanceRelationDetectedAtClientSide");
+                span.setMsg("ClientServiceId: " + clientServiceId + ", 
ServerServiceId: " + serverServiceId + ", Duration: " + duration);
+            }
+            return loadInstanceRelationDetectedAtClientSide(clientServiceId, 
serverServiceId, duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> loadEndpointRelationDebuggable(Duration 
duration,
+                                               String destEndpointId) throws 
IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadEndpointRelation");
+                span.setMsg("Duration: " + duration + ", DestEndpointId: " + 
destEndpointId);
+            }
+            return loadEndpointRelation(duration, destEndpointId);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadProcessRelationDetectedAtClientSideDebuggable(String serviceInstanceId,
+                                                                  Duration 
duration) throws IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadProcessRelationDetectedAtClientSide");
+                span.setMsg("ServiceInstanceId: " + serviceInstanceId + ", 
Duration: " + duration);
+            }
+            return loadProcessRelationDetectedAtClientSide(serviceInstanceId, 
duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
+    default List<Call.CallDetail> 
loadProcessRelationDetectedAtServerSideDebuggable(String serviceInstanceId,
+                                                                  Duration 
duration) throws IOException {
+        DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
+        DebuggingSpan span = null;
+        try {
+            if (traceContext != null) {
+                span = traceContext.createSpan("Query Dao: 
loadProcessRelationDetectedAtServerSide");
+                span.setMsg("ServiceInstanceId: " + serviceInstanceId + ", 
Duration: " + duration);
+            }
+            return loadProcessRelationDetectedAtServerSide(serviceInstanceId, 
duration);
+        } finally {
+            if (traceContext != null && span != null) {
+                traceContext.stopSpan(span);
+            }
+        }
+    }
+
     /**
      * Query {@link ServiceRelationServerSideMetrics} through the given 
conditions
      */
diff --git 
a/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
index db761b08b6..4e8b8c1982 100644
--- 
a/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
+++ 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingHTTPHandler.java
@@ -27,6 +27,7 @@ import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
 import com.linecorp.armeria.common.AggregatedHttpResponse;
 import com.linecorp.armeria.server.annotation.Default;
+import com.linecorp.armeria.server.annotation.ExceptionHandler;
 import com.linecorp.armeria.server.annotation.Get;
 import com.linecorp.armeria.server.annotation.Param;
 import java.util.ArrayList;
@@ -39,11 +40,16 @@ import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.mqe.rt.type.ExpressionResult;
 import org.apache.skywalking.oap.query.debug.mqe.DebuggingMQERsp;
+import 
org.apache.skywalking.oap.query.debug.topology.DebuggingQueryEndpointTopologyRsp;
+import 
org.apache.skywalking.oap.query.debug.topology.DebuggingQueryInstanceTopologyRsp;
+import 
org.apache.skywalking.oap.query.debug.topology.DebuggingQueryProcessTopologyRsp;
+import 
org.apache.skywalking.oap.query.debug.topology.DebuggingQueryServiceTopologyRsp;
 import org.apache.skywalking.oap.query.debug.trace.DebuggingQueryTraceBriefRsp;
 import org.apache.skywalking.oap.query.debug.trace.DebuggingQueryTraceRsp;
 import 
org.apache.skywalking.oap.query.debug.trace.zipkin.DebuggingZipkinQueryTraceRsp;
 import 
org.apache.skywalking.oap.query.debug.trace.zipkin.DebuggingZipkinQueryTracesRsp;
 import org.apache.skywalking.oap.query.graphql.resolver.MetricsExpressionQuery;
+import org.apache.skywalking.oap.query.graphql.resolver.TopologyQuery;
 import org.apache.skywalking.oap.query.graphql.resolver.TraceQuery;
 import org.apache.skywalking.oap.query.zipkin.ZipkinQueryConfig;
 import org.apache.skywalking.oap.query.zipkin.handler.ZipkinQueryHandler;
@@ -56,8 +62,12 @@ import 
org.apache.skywalking.oap.server.core.query.enumeration.Step;
 import org.apache.skywalking.oap.server.core.query.input.Duration;
 import org.apache.skywalking.oap.server.core.query.input.Entity;
 import org.apache.skywalking.oap.server.core.query.input.TraceQueryCondition;
+import org.apache.skywalking.oap.server.core.query.type.EndpointTopology;
 import org.apache.skywalking.oap.server.core.query.type.Pagination;
+import org.apache.skywalking.oap.server.core.query.type.ProcessTopology;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
+import 
org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
+import org.apache.skywalking.oap.server.core.query.type.Topology;
 import org.apache.skywalking.oap.server.core.query.type.Trace;
 import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
 import org.apache.skywalking.oap.server.core.query.type.TraceState;
@@ -69,11 +79,13 @@ import 
org.apache.skywalking.oap.server.library.module.ModuleManager;
 import zipkin2.Span;
 
 @Slf4j
+@ExceptionHandler(DebuggingQueryExceptionHandler.class)
 public class DebuggingHTTPHandler {
     private final ServerStatusService serverStatusService;
     private final MetricsExpressionQuery mqeQuery;
     private final TraceQuery traceQuery;
     private final ZipkinQueryHandler zipkinQueryHandler;
+    private final TopologyQuery topologyQuery;
     final DebuggingQueryConfig config;
 
     public DebuggingHTTPHandler(final ModuleManager manager, final 
DebuggingQueryConfig config) {
@@ -85,6 +97,7 @@ public class DebuggingHTTPHandler {
         this.traceQuery = new TraceQuery(manager);
         //use zipkin default config for debugging
         this.zipkinQueryHandler = new ZipkinQueryHandler(new 
ZipkinQueryConfig(), manager);
+        this.topologyQuery = new TopologyQuery(manager);
     }
 
     @Get("/debugging/config/dump")
@@ -266,6 +279,104 @@ public class DebuggingHTTPHandler {
         }
     }
 
+    @SneakyThrows
+    @Get("/debugging/query/topology/getGlobalTopology")
+    public String getGlobalTopology(@Param("startTime") String startTime,
+                                 @Param("endTime") String endTime,
+                                 @Param("step") String step,
+                                 @Param("serviceLayer") Optional<String> 
serviceLayer) {
+        Duration duration = new Duration();
+        duration.setStart(startTime);
+        duration.setEnd(endTime);
+        duration.setStep(Step.valueOf(step));
+        Topology topology = topologyQuery.getGlobalTopology(duration, 
serviceLayer.orElse(null), true);
+        DebuggingQueryServiceTopologyRsp result = new 
DebuggingQueryServiceTopologyRsp(
+            topology.getNodes(), topology.getCalls(), 
transformTrace(topology.getDebuggingTrace()));
+        return transToYAMLString(result);
+    }
+
+    @SneakyThrows
+    @Get("/debugging/query/topology/getServicesTopology")
+    public String getServicesTopology(@Param("startTime") String startTime,
+                                    @Param("endTime") String endTime,
+                                    @Param("step") String step,
+                                    @Param("serviceLayer") String serviceLayer,
+                                    @Param("services") String services) {
+        Duration duration = new Duration();
+        duration.setStart(startTime);
+        duration.setEnd(endTime);
+        duration.setStep(Step.valueOf(step));
+
+        List<String> ids = Arrays.stream(services.split(Const.COMMA))
+                                 .map(name -> 
IDManager.ServiceID.buildId(name, Layer.nameOf(serviceLayer).isNormal()))
+                                 .collect(Collectors.toList());
+        Topology topology = topologyQuery.getServicesTopology(ids, duration, 
true);
+        DebuggingQueryServiceTopologyRsp result = new 
DebuggingQueryServiceTopologyRsp(
+            topology.getNodes(), topology.getCalls(), 
transformTrace(topology.getDebuggingTrace()));
+        return transToYAMLString(result);
+    }
+
+    @SneakyThrows
+    @Get("/debugging/query/topology/getServiceInstanceTopology")
+    public String getServiceInstanceTopology(@Param("startTime") String 
startTime,
+                                             @Param("endTime") String endTime,
+                                             @Param("step") String step,
+                                             @Param("clientService") String 
clientService,
+                                             @Param("serverService") String 
serverService,
+                                             @Param("clientServiceLayer") 
String clientServiceLayer,
+                                             @Param("serverServiceLayer") 
String serverServiceLayer) {
+        Duration duration = new Duration();
+        duration.setStart(startTime);
+        duration.setEnd(endTime);
+        duration.setStep(Step.valueOf(step));
+        String clientServiceId = IDManager.ServiceID.buildId(clientService, 
Layer.nameOf(clientServiceLayer).isNormal());
+        String serverServiceId = IDManager.ServiceID.buildId(serverService, 
Layer.nameOf(serverServiceLayer).isNormal());
+        ServiceInstanceTopology topology = 
topologyQuery.getServiceInstanceTopology(clientServiceId, serverServiceId, 
duration, true);
+        DebuggingQueryInstanceTopologyRsp result = new 
DebuggingQueryInstanceTopologyRsp(
+            topology.getNodes(), topology.getCalls(), 
transformTrace(topology.getDebuggingTrace()));
+        return transToYAMLString(result);
+    }
+
+    @SneakyThrows
+    @Get("/debugging/query/topology/getEndpointDependencies")
+    public String getEndpointDependencies(@Param("startTime") String startTime,
+                                          @Param("endTime") String endTime,
+                                          @Param("step") String step,
+                                          @Param("service") String service,
+                                          @Param("serviceLayer") String 
serviceLayer,
+                                          @Param("endpoint") String endpoint) {
+        Duration duration = new Duration();
+        duration.setStart(startTime);
+        duration.setEnd(endTime);
+        duration.setStep(Step.valueOf(step));
+        String endpointId = IDManager.EndpointID.buildId(
+            IDManager.ServiceID.buildId(service, 
Layer.nameOf(serviceLayer).isNormal()), endpoint);
+        EndpointTopology topology = 
topologyQuery.getEndpointDependencies(endpointId, duration, true);
+        DebuggingQueryEndpointTopologyRsp result = new 
DebuggingQueryEndpointTopologyRsp(
+            topology.getNodes(), topology.getCalls(), 
transformTrace(topology.getDebuggingTrace()));
+        return transToYAMLString(result);
+    }
+
+    @SneakyThrows
+    @Get("/debugging/query/topology/getProcessTopology")
+    public String getProcessTopology(@Param("startTime") String startTime,
+                                     @Param("endTime") String endTime,
+                                     @Param("step") String step,
+                                     @Param("service") String service,
+                                     @Param("serviceLayer") String 
serviceLayer,
+                                     @Param("instance") String process) {
+        Duration duration = new Duration();
+        duration.setStart(startTime);
+        duration.setEnd(endTime);
+        duration.setStep(Step.valueOf(step));
+        String instanceId = IDManager.ServiceInstanceID.buildId(
+            IDManager.ServiceID.buildId(service, 
Layer.nameOf(serviceLayer).isNormal()), process);
+        ProcessTopology topology = 
topologyQuery.getProcessTopology(instanceId, duration, true);
+        DebuggingQueryProcessTopologyRsp result = new 
DebuggingQueryProcessTopologyRsp(
+            topology.getNodes(), topology.getCalls(), 
transformTrace(topology.getDebuggingTrace()));
+        return transToYAMLString(result);
+    }
+
     private DebuggingTraceRsp transformTrace(DebuggingTrace trace) {
         Map<Integer, DebuggingSpanRsp> spanMap = trace.getSpans().stream()
                                                       
.collect(Collectors.toMap(
diff --git 
a/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingQueryExceptionHandler.java
 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingQueryExceptionHandler.java
new file mode 100644
index 0000000000..5bede1f430
--- /dev/null
+++ 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/DebuggingQueryExceptionHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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.debug;
+
+import com.linecorp.armeria.common.HttpRequest;
+import com.linecorp.armeria.common.HttpResponse;
+import com.linecorp.armeria.server.ServiceRequestContext;
+import com.linecorp.armeria.server.annotation.ExceptionHandlerFunction;
+import lombok.extern.slf4j.Slf4j;
+
+import static com.linecorp.armeria.common.HttpStatus.BAD_REQUEST;
+import static com.linecorp.armeria.common.HttpStatus.INTERNAL_SERVER_ERROR;
+import static com.linecorp.armeria.common.MediaType.ANY_TEXT_TYPE;
+
+@Slf4j
+public class DebuggingQueryExceptionHandler implements 
ExceptionHandlerFunction {
+    @Override
+    public HttpResponse handleException(final ServiceRequestContext ctx, final 
HttpRequest req, final Throwable cause) {
+        String rspMsg = cause.getMessage() != null ? cause.getMessage() : 
cause.getClass().getSimpleName();
+        // Response msg for illegal query args.
+        if (cause instanceof IllegalArgumentException) {
+            log.error(cause.getMessage(), cause);
+            return HttpResponse.of(BAD_REQUEST, ANY_TEXT_TYPE, rspMsg);
+        } else {
+            log.error(cause.getMessage(), cause);
+            return HttpResponse.of(INTERNAL_SERVER_ERROR, ANY_TEXT_TYPE, 
rspMsg);
+        }
+    }
+}
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryEndpointTopologyRsp.java
similarity index 69%
copy from 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
copy to 
oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryEndpointTopologyRsp.java
index 2510d9117f..483ca7fbf3 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/EndpointTopology.java
+++ 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryEndpointTopologyRsp.java
@@ -16,19 +16,19 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug.topology;
 
-import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.oap.query.debug.DebuggingTraceRsp;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.EndpointNode;
 
+@RequiredArgsConstructor
 @Getter
-public class EndpointTopology {
+public class DebuggingQueryEndpointTopologyRsp {
     private final List<EndpointNode> nodes;
     private final List<Call> calls;
-
-    public EndpointTopology() {
-        this.nodes = new ArrayList<>();
-        this.calls = new ArrayList<>();
-    }
+    private final DebuggingTraceRsp debuggingTrace;
 }
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryInstanceTopologyRsp.java
similarity index 69%
copy from 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
copy to 
oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryInstanceTopologyRsp.java
index 30070d1335..a7d1c1db90 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ServiceInstanceTopology.java
+++ 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryInstanceTopologyRsp.java
@@ -16,20 +16,19 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug.topology;
 
-import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.oap.query.debug.DebuggingTraceRsp;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.ServiceInstanceNode;
 
+@RequiredArgsConstructor
 @Getter
-public class ServiceInstanceTopology {
-
+public class DebuggingQueryInstanceTopologyRsp {
     private final List<ServiceInstanceNode> nodes;
     private final List<Call> calls;
-
-    public ServiceInstanceTopology() {
-        this.nodes = new ArrayList<>();
-        this.calls = new ArrayList<>();
-    }
+    private final DebuggingTraceRsp debuggingTrace;
 }
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryProcessTopologyRsp.java
similarity index 69%
copy from 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
copy to 
oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryProcessTopologyRsp.java
index 79518aa05e..eb0e5bf8be 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/ProcessTopology.java
+++ 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryProcessTopologyRsp.java
@@ -16,20 +16,19 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug.topology;
 
-import lombok.Getter;
-
-import java.util.ArrayList;
 import java.util.List;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.oap.query.debug.DebuggingTraceRsp;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.ProcessNode;
 
+@RequiredArgsConstructor
 @Getter
-public class ProcessTopology {
+public class DebuggingQueryProcessTopologyRsp {
     private final List<ProcessNode> nodes;
     private final List<Call> calls;
-
-    public ProcessTopology() {
-        this.nodes = new ArrayList<>();
-        this.calls = new ArrayList<>();
-    }
-}
\ No newline at end of file
+    private final DebuggingTraceRsp debuggingTrace;
+}
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryServiceTopologyRsp.java
similarity index 69%
copy from 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
copy to 
oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryServiceTopologyRsp.java
index 7b571157db..c421787c38 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Topology.java
+++ 
b/oap-server/server-query-plugin/debugging-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/topology/DebuggingQueryServiceTopologyRsp.java
@@ -16,19 +16,19 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.query.type;
+package org.apache.skywalking.oap.query.debug.topology;
 
-import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.skywalking.oap.query.debug.DebuggingTraceRsp;
+import org.apache.skywalking.oap.server.core.query.type.Call;
+import org.apache.skywalking.oap.server.core.query.type.Node;
 
+@RequiredArgsConstructor
 @Getter
-public class Topology {
+public class DebuggingQueryServiceTopologyRsp {
     private final List<Node> nodes;
     private final List<Call> calls;
-
-    public Topology() {
-        this.nodes = new ArrayList<>();
-        this.calls = new ArrayList<>();
-    }
+    private final DebuggingTraceRsp debuggingTrace;
 }
diff --git 
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
 
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
index 7328a272af..b161b4cbb3 100644
--- 
a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
+++ 
b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TopologyQuery.java
@@ -29,8 +29,12 @@ import 
org.apache.skywalking.oap.server.core.query.type.EndpointTopology;
 import org.apache.skywalking.oap.server.core.query.type.ProcessTopology;
 import 
org.apache.skywalking.oap.server.core.query.type.ServiceInstanceTopology;
 import org.apache.skywalking.oap.server.core.query.type.Topology;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
+import 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 
+import static 
org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext.TRACE_CONTEXT;
+
 public class TopologyQuery implements GraphQLQueryResolver {
 
     private final ModuleManager moduleManager;
@@ -47,31 +51,97 @@ public class TopologyQuery implements GraphQLQueryResolver {
         return queryService;
     }
 
-    public Topology getGlobalTopology(final Duration duration, final String 
layer) throws IOException {
-        return getQueryService().getGlobalTopology(duration, layer);
+    public Topology getGlobalTopology(final Duration duration,
+                                      final String layer,
+                                      final boolean debug) throws IOException {
+        DebuggingTraceContext traceContext = new DebuggingTraceContext(
+            "Duration: " + duration + ", Layer: " + layer, debug, false);
+        DebuggingTraceContext.TRACE_CONTEXT.set(traceContext);
+        DebuggingSpan span = traceContext.createSpan("Query global topology");
+        try {
+            Topology topology = getQueryService().getGlobalTopology(duration, 
layer);
+            if (debug) {
+                topology.setDebuggingTrace(traceContext.getExecTrace());
+            }
+            return topology;
+        } finally {
+            traceContext.stopSpan(span);
+            traceContext.stopTrace();
+            TRACE_CONTEXT.remove();
+        }
     }
 
-    public Topology getServiceTopology(final String serviceId, final Duration 
duration) throws IOException {
-        List<String> selectedServiceList = new ArrayList<>(1);
-        selectedServiceList.add(serviceId);
-        return this.getServicesTopology(selectedServiceList, duration);
+    public Topology getServiceTopology(final String serviceId,
+                                       final Duration duration,
+                                       final boolean debug) throws IOException 
{
+        DebuggingTraceContext traceContext = new DebuggingTraceContext(
+            "ServiceId: " + serviceId + "Duration: " + duration, debug, false);
+        DebuggingTraceContext.TRACE_CONTEXT.set(traceContext);
+        DebuggingSpan span = traceContext.createSpan("Query service topology");
+        try {
+            List<String> selectedServiceList = new ArrayList<>(1);
+            selectedServiceList.add(serviceId);
+            Topology topology = this.getServicesTopology(selectedServiceList, 
duration, debug);
+            if (debug) {
+                topology.setDebuggingTrace(traceContext.getExecTrace());
+            }
+            return topology;
+        } finally {
+
+            traceContext.stopSpan(span);
+            traceContext.stopTrace();
+            TRACE_CONTEXT.remove();
+        }
     }
 
-    public Topology getServicesTopology(final List<String> serviceIds, final 
Duration duration) throws IOException {
-        return getQueryService().getServiceTopology(duration, serviceIds);
+    public Topology getServicesTopology(final List<String> serviceIds,
+                                        final Duration duration,
+                                        final boolean debug) throws 
IOException {
+        DebuggingTraceContext traceContext = new DebuggingTraceContext(
+            "ServiceIds: " + serviceIds + "Duration: " + duration, debug, 
false);
+        DebuggingTraceContext.TRACE_CONTEXT.set(traceContext);
+        DebuggingSpan span = traceContext.createSpan("Query service topology");
+        try {
+            Topology topology = getQueryService().getServiceTopology(duration, 
serviceIds);
+            if (debug) {
+                topology.setDebuggingTrace(traceContext.getExecTrace());
+            }
+            return topology;
+        } finally {
+            traceContext.stopSpan(span);
+            traceContext.stopTrace();
+            TRACE_CONTEXT.remove();
+        }
     }
 
     public ServiceInstanceTopology getServiceInstanceTopology(final String 
clientServiceId,
                                                               final String 
serverServiceId,
-                                                              final Duration 
duration) throws IOException {
-        return getQueryService().getServiceInstanceTopology(
-            clientServiceId, serverServiceId,
-            duration
+                                                              final Duration 
duration,
+                                                              final boolean 
debug) throws IOException {
+        DebuggingTraceContext traceContext = new DebuggingTraceContext(
+            "ClientServiceId: " + clientServiceId + ", ServerServiceId: " + 
serverServiceId + ", Duration: " + duration,
+            debug, false
         );
+        DebuggingTraceContext.TRACE_CONTEXT.set(traceContext);
+        DebuggingSpan span = traceContext.createSpan("Query service instance 
topology");
+        try {
+            ServiceInstanceTopology topology = 
getQueryService().getServiceInstanceTopology(
+                clientServiceId, serverServiceId,
+                duration
+            );
+            if (debug) {
+                topology.setDebuggingTrace(traceContext.getExecTrace());
+            }
+            return topology;
+        } finally {
+            traceContext.stopSpan(span);
+            traceContext.stopTrace();
+            TRACE_CONTEXT.remove();
+        }
     }
 
     /**
-     * Replaced by {@link #getEndpointDependencies(String, Duration)}
+     * Replaced by {@link #getEndpointDependencies(String, Duration, boolean)}
      */
     @Deprecated
     public Topology getEndpointTopology(final String endpointId, final 
Duration duration) throws IOException {
@@ -79,11 +149,40 @@ public class TopologyQuery implements GraphQLQueryResolver 
{
     }
 
     public EndpointTopology getEndpointDependencies(final String endpointId,
-                                                    final Duration duration) 
throws IOException {
-        return getQueryService().getEndpointDependencies(duration, endpointId);
+                                                    final Duration duration,
+                                                    final boolean debug) 
throws IOException {
+        DebuggingTraceContext traceContext = new DebuggingTraceContext(
+            "EndpointId: " + endpointId + ", Duration: " + duration, debug, 
false);
+        DebuggingTraceContext.TRACE_CONTEXT.set(traceContext);
+        DebuggingSpan span = traceContext.createSpan("Query endpoint 
dependencies");
+        try {
+            EndpointTopology topology = 
getQueryService().getEndpointDependencies(duration, endpointId);
+            if (debug) {
+                topology.setDebuggingTrace(traceContext.getExecTrace());
+            }
+            return topology;
+        } finally {
+            traceContext.stopSpan(span);
+            traceContext.stopTrace();
+            TRACE_CONTEXT.remove();
+        }
     }
 
-    public ProcessTopology getProcessTopology(final String instanceId, final 
Duration duration) throws Exception {
-        return getQueryService().getProcessTopology(instanceId, duration);
+    public ProcessTopology getProcessTopology(final String instanceId, final 
Duration duration, final boolean debug) throws Exception {
+        DebuggingTraceContext traceContext = new DebuggingTraceContext(
+            "InstanceId: " + instanceId + ", Duration: " + duration, debug, 
false);
+        DebuggingTraceContext.TRACE_CONTEXT.set(traceContext);
+        DebuggingSpan span = traceContext.createSpan("Query process topology");
+        try {
+            ProcessTopology topology = 
getQueryService().getProcessTopology(instanceId, duration);
+            if (debug) {
+                topology.setDebuggingTrace(traceContext.getExecTrace());
+            }
+            return topology;
+        } finally {
+            traceContext.stopSpan(span);
+            traceContext.stopTrace();
+            TRACE_CONTEXT.remove();
+        }
     }
 }
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 ee577ac283..e93484a89c 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 ee577ac283c1e0b418d9da502deba41dfbcb28c3
+Subproject commit e93484a89c9d59fda8303f1dc3cac78e64f56bf7
diff --git 
a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java
 
b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java
index e1cd297ee3..e91fe30d43 100644
--- 
a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java
+++ 
b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java
@@ -34,6 +34,7 @@ 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.UnexpectedException;
+import org.apache.skywalking.oap.server.core.analysis.DownSampling;
 import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import 
org.apache.skywalking.oap.server.core.analysis.manual.relation.endpoint.EndpointRelationServerSideMetrics;
 import 
org.apache.skywalking.oap.server.core.analysis.manual.relation.instance.ServiceInstanceRelationClientSideMetrics;
@@ -205,7 +206,7 @@ public class BanyanDBTopologyQueryDAO extends 
AbstractBanyanDBDAO implements ITo
         final String modelName = detectPoint == DetectPoint.SERVER ? 
ServiceInstanceRelationServerSideMetrics.INDEX_NAME :
                 ServiceInstanceRelationClientSideMetrics.INDEX_NAME;
         MetadataRegistry.Schema schema = 
MetadataRegistry.INSTANCE.findMetadata(modelName, duration.getStep());
-        MeasureQueryResponse resp = query(schema,
+        MeasureQueryResponse resp = queryDebuggable(schema,
                 ImmutableSet.of(
                         Metrics.ENTITY_ID
                 ),
@@ -269,7 +270,7 @@ public class BanyanDBTopologyQueryDAO extends 
AbstractBanyanDBDAO implements ITo
             timestampRange = new 
TimestampRange(TimeBucket.getTimestamp(startTB), 
TimeBucket.getTimestamp(endTB));
         }
         MetadataRegistry.Schema schema = 
MetadataRegistry.INSTANCE.findMetadata(EndpointRelationServerSideMetrics.INDEX_NAME,
 duration.getStep());
-        MeasureQueryResponse resp = query(schema,
+        MeasureQueryResponse resp = queryDebuggable(schema,
                 ImmutableSet.of(
                         Metrics.ENTITY_ID
                 ),
@@ -303,8 +304,9 @@ public class BanyanDBTopologyQueryDAO extends 
AbstractBanyanDBDAO implements ITo
         }
         final String modelName = detectPoint == DetectPoint.SERVER ? 
ProcessRelationServerSideMetrics.INDEX_NAME :
                 ProcessRelationClientSideMetrics.INDEX_NAME;
-        MetadataRegistry.Schema schema = 
MetadataRegistry.INSTANCE.findMetadata(modelName, duration.getStep());
-        MeasureQueryResponse resp = query(schema,
+        // process relation only has minute data
+        MetadataRegistry.Schema schema = 
MetadataRegistry.INSTANCE.findMetadata(modelName, DownSampling.Minute);
+        MeasureQueryResponse resp = queryDebuggable(schema,
                 ImmutableSet.of(Metrics.ENTITY_ID, 
ProcessRelationClientSideMetrics.COMPONENT_ID),
                 Collections.emptySet(), timestampRange, new 
QueryBuilder<MeasureQuery>() {
                     @Override
diff --git 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
index 4af0614790..e070eccb6b 100644
--- 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
+++ 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/EsDAO.java
@@ -65,6 +65,10 @@ public abstract class EsDAO extends 
AbstractDAO<ElasticSearchClient> {
         }
     }
 
+    protected SearchResponse searchDebuggable(String indexName, Search search) 
{
+        return searchDebuggable(indexName, search, null);
+    }
+
     protected SearchResponse searchDebuggable(String indexName, Search search, 
SearchParams params) {
         DebuggingTraceContext traceContext = 
DebuggingTraceContext.TRACE_CONTEXT.get();
         DebuggingSpan span = null;
diff --git 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
index 65023469eb..ce6663f927 100644
--- 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
+++ 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/RecordsQueryEsDAO.java
@@ -71,7 +71,7 @@ public class RecordsQueryEsDAO extends EsDAO implements 
IRecordsQueryDAO {
                   );
         final SearchResponse response = searchDebuggable(
             
IndexController.LogicIndicesRegister.getPhysicalTableName(condition.getName()),
-            search.build(), null
+            search.build()
         );
 
         List<Record> results = new ArrayList<>(condition.getTopN());
diff --git 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
index 0d4f47a1f0..a226c265bb 100644
--- 
a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
+++ 
b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TopologyQueryEsDAO.java
@@ -260,7 +260,7 @@ public class TopologyQueryEsDAO extends EsDAO implements 
ITopologyQueryDAO {
         if (IndexController.LogicIndicesRegister.isMergedTable(indexName)) {
             
query.must(Query.term(IndexController.LogicIndicesRegister.METRIC_TABLE_NAME, 
indexName));
         }
-        final SearchResponse response = getClient().search(index, 
sourceBuilder.build());
+        final SearchResponse response = searchDebuggable(index, 
sourceBuilder.build());
 
         final List<Call.CallDetail> calls = new ArrayList<>();
         final Map<String, Object> entityTerms =
@@ -300,7 +300,7 @@ public class TopologyQueryEsDAO extends EsDAO implements 
ITopologyQueryDAO {
 
         final String index =
             
IndexController.LogicIndicesRegister.getPhysicalTableName(indexName);
-        final SearchResponse response = getClient().search(index, 
sourceBuilder.build());
+        final SearchResponse response = searchDebuggable(index, 
sourceBuilder.build());
 
         final List<Call.CallDetail> calls = new ArrayList<>();
         final Map<String, Object> entityTerms =
@@ -337,7 +337,7 @@ public class TopologyQueryEsDAO extends EsDAO implements 
ITopologyQueryDAO {
 
         final String index =
             
IndexController.LogicIndicesRegister.getPhysicalTableName(indexName);
-        SearchResponse response = getClient().search(index, 
sourceBuilder.build());
+        SearchResponse response = searchDebuggable(index, 
sourceBuilder.build());
 
         List<Call.CallDetail> calls = new ArrayList<>();
         final Map<String, Object> entityTerms =
@@ -365,7 +365,7 @@ public class TopologyQueryEsDAO extends EsDAO implements 
ITopologyQueryDAO {
 
         final String index =
             
IndexController.LogicIndicesRegister.getPhysicalTableName(indexName);
-        final SearchResponse response = getClient().search(index, 
sourceBuilder.build());
+        final SearchResponse response = searchDebuggable(index, 
sourceBuilder.build());
 
         final List<Call.CallDetail> calls = new ArrayList<>();
         final Map<String, Object> entityTerms =

Reply via email to