Skip to content

Commit

Permalink
Support tracing topology query for debugging (apache#12413)
Browse files Browse the repository at this point in the history
  • Loading branch information
wankai123 committed Jul 4, 2024
1 parent e96b75f commit 98ef399
Show file tree
Hide file tree
Showing 25 changed files with 1,188 additions and 143 deletions.
13 changes: 7 additions & 6 deletions docs/en/api/query-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
```

Expand Down
1 change: 1 addition & 0 deletions docs/en/changes/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
403 changes: 343 additions & 60 deletions docs/en/debugging/query-tracing.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
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;
Expand Down Expand Up @@ -68,6 +70,22 @@ public ProcessTopologyBuilder(ModuleManager moduleManager, StorageModels storage
.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: {}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
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;

Expand All @@ -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) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
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;
Expand Down Expand Up @@ -67,6 +69,22 @@ private MetadataQueryService getMetadataQueryService() {
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<>();
Expand Down
Loading

0 comments on commit 98ef399

Please sign in to comment.