This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push: new 859a462382 GraphQL API: metadata, topology, log and trace support query by name. (#13388) 859a462382 is described below commit 859a46238291cc0b64b04697c8fb1c5de84a866f Author: Wan Kai <wankai...@foxmail.com> AuthorDate: Tue Jul 29 17:42:19 2025 +0800 GraphQL API: metadata, topology, log and trace support query by name. (#13388) --- docs/en/api/query-protocol.md | 12 +- docs/en/changes/changes.md | 1 + docs/en/debugging/query-tracing.md | 9 +- .../server/core/query/input/EndpointCondition.java | 55 +++++++++ .../server/core/query/input/InstanceCondition.java | 54 +++++++++ .../core/query/input/LogQueryConditionByName.java | 67 +++++++++++ .../server/core/query/input/ServiceCondition.java | 47 ++++++++ .../query/input/TraceQueryConditionByName.java | 69 ++++++++++++ .../oap/query/graphql/resolver/LogQuery.java | 33 ++++++ .../query/graphql/resolver/MetadataQueryV2.java | 12 ++ .../oap/query/graphql/resolver/TopologyQuery.java | 124 +++++++++++++++++++++ .../oap/query/graphql/resolver/TraceQuery.java | 34 ++++++ .../src/main/resources/query-protocol | 2 +- test/e2e-v2/cases/gateway/docker-compose.yml | 24 +--- 14 files changed, 522 insertions(+), 21 deletions(-) diff --git a/docs/en/api/query-protocol.md b/docs/en/api/query-protocol.md index 3ca351a58f..8ba94a08a4 100644 --- a/docs/en/api/query-protocol.md +++ b/docs/en/api/query-protocol.md @@ -28,12 +28,15 @@ extend type Query { # Read service instance list. listInstances(duration: Duration!, serviceId: ID!): [ServiceInstance!]! + listInstancesByName(duration: Duration!, service: ServiceCondition!): [ServiceInstance!]! # Search and find service instance according to given ID. Return null if not existing. getInstance(instanceId: String!): ServiceInstance # Search and find matched endpoints according to given service and keyword(optional) # If no keyword, randomly choose endpoint based on `limit` value. - findEndpoint(keyword: String, serviceId: ID!, limit: Int!): [Endpoint!]! + # If duration is nil mean get all endpoints, otherwise, get the endpoint list in the given duration. + findEndpoint(keyword: String, serviceId: ID!, limit: Int!, duration: Duration): [Endpoint!]! + findEndpointByName(keyword: String, service: ServiceCondition!, limit: Int!, duration: Duration): [Endpoint!]! getEndpointInfo(endpointId: ID!): EndpointInfo # Read process list. @@ -66,17 +69,22 @@ extend type Query { getGlobalTopology(duration: Duration!, layer: String, debug: Boolean): Topology # Query the topology, based on the given service getServiceTopology(serviceId: ID!, duration: Duration!, debug: Boolean): Topology + getServiceTopologyByName(service: ServiceCondition!, 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 + getServicesTopologyByNames(services: [ServiceCondition!]!, 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 + getServiceInstanceTopologyByName(clientService: ServiceCondition!, serverService: ServiceCondition!, 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!, debug: Boolean): EndpointTopology + getEndpointDependenciesByName(endpoint: EndpointCondition!, duration: Duration!, debug: Boolean): EndpointTopology # Query the topology, based on the given instance getProcessTopology(serviceInstanceId: ID!, duration: Duration!, debug: Boolean): ProcessTopology + getProcessTopologyByName(instance: InstanceCondition!, duration: Duration!, debug: Boolean): ProcessTopology } ``` @@ -138,6 +146,7 @@ extend type Query { # Return true if the current storage implementation supports fuzzy query for logs. supportQueryLogsByKeywords: Boolean! queryLogs(condition: LogQueryCondition, debug: Boolean): Logs + queryLogsByName(condition: LogQueryConditionByName, debug: Boolean): Logs # Test the logs and get the results of the LAL output. test(requests: LogTestRequest!): LogTestResponse! # Read the list of searchable keys @@ -158,6 +167,7 @@ full log text fuzzy queries, while others do not due to considerations related t extend type Query { # Search segment list with given conditions queryBasicTraces(condition: TraceQueryCondition, debug: Boolean): TraceBrief + queryBasicTracesByName(condition: TraceQueryConditionByName, debug: Boolean): TraceBrief # Read the specific trace ID with given trace ID queryTrace(traceId: ID!, debug: Boolean): Trace # Only for BanyanDB, can be used to query the trace in the cold stage. diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md index 78ecd4b073..df5da024f8 100644 --- a/docs/en/changes/changes.md +++ b/docs/en/changes/changes.md @@ -45,6 +45,7 @@ * Fix analysis tracing profiling span failure in ES storage. * Add UI dashboard for Ruby runtime metrics. * Tracing Query Execution HTTP APIs: make the argument `service layer` optional. +* GraphQL API: metadata, topology, log and trace support query by name. #### UI diff --git a/docs/en/debugging/query-tracing.md b/docs/en/debugging/query-tracing.md index dd1805efd3..966f6e31aa 100644 --- a/docs/en/debugging/query-tracing.md +++ b/docs/en/debugging/query-tracing.md @@ -31,7 +31,7 @@ SkyWalking OAP provides the metrics/trace/log/topology query tracing to help use The query tracing service is provided within the OAP rest server, which could be accessed through HTTP GET `http://{core restHost}:{core restPort}/debugging/query/...`. -**Note:** The `layer` of the service is optional, but if the service is virtual then required, such the `layer` is `VIRTUAL_DATABASE/VIRTUAL_MQ/VIRTUAL_GATEWAY`. +**Note:** The `layer` of the service is optional, but if the service is virtual then required, such the `layer` is `UNDEFINED/VIRTUAL_DATABASE/VIRTUAL_MQ/VIRTUAL_GATEWAY`. ### Tracing MQE Execution - URL: HTTP GET `http://{core restHost}:{core restPort}/debugging/query/mqe?{parameters}`. @@ -694,6 +694,7 @@ the debuggingTrace will include the BanyanDB internal execution trace info, such extend type Query { # Search segment list with given conditions queryBasicTraces(condition: TraceQueryCondition, debug: Boolean): TraceBrief + queryBasicTracesByName(condition: TraceQueryConditionByName, debug: Boolean): TraceBrief # Read the specific trace ID with given trace ID queryTrace(traceId: ID!, debug: Boolean): Trace ... @@ -732,16 +733,21 @@ extend type Query { getGlobalTopology(duration: Duration!, layer: String, debug: Boolean): Topology # Query the topology, based on the given service getServiceTopology(serviceId: ID!, duration: Duration!, debug: Boolean): Topology + getServiceTopologyByName(service: ServiceCondition!, 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 + getServicesTopologyByNames(services: [ServiceCondition!]!, 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 + getServiceInstanceTopologyByName(clientService: ServiceCondition!, serverService: ServiceCondition!, duration: Duration!, debug: Boolean): ServiceInstanceTopology ... # v2 of getEndpointTopology getEndpointDependencies(endpointId: ID!, duration: Duration!, debug: Boolean): EndpointTopology + getEndpointDependenciesByName(endpoint: EndpointCondition!, duration: Duration!, debug: Boolean): EndpointTopology # Query the topology, based on the given instance getProcessTopology(serviceInstanceId: ID!, duration: Duration!, debug: Boolean): ProcessTopology + getProcessTopologyByName(instance: InstanceCondition!, duration: Duration!, debug: Boolean): ProcessTopology } ``` @@ -786,6 +792,7 @@ just enable the debug parameter to true. extend type Query { ... queryLogs(condition: LogQueryCondition, debug: Boolean): Logs + queryLogsByName(condition: LogQueryConditionByName, debug: Boolean): Logs ... } ``` diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/EndpointCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/EndpointCondition.java new file mode 100644 index 0000000000..44f3980f59 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/EndpointCondition.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.query.input; + +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.apache.skywalking.oap.server.core.analysis.IDManager; +import org.apache.skywalking.oap.server.core.analysis.Layer; + +@Setter +@Getter +@ToString +public class EndpointCondition { + private String serviceName; + private String endpointName; + @Nullable + private String layer; + + /** + * Get the endpoint ID based on the service name, endpoint name and {@link Layer} name. + * The layer can be null, in which case it defaults to a normal layer. + * Otherwise, it uses the provided layer to determine if the service is normal or not. + * The un-normal layer includes VIRTUAL_DATABASE/VIRTUAL_MQ/VIRTUAL_GATEWAY, etc. + * + * @return endpoint ID + */ + public String getEndpointId() { + // default to true if service layer is not provided + return IDManager.EndpointID.buildId( + IDManager.ServiceID.buildId( + serviceName, + layer == null || Layer.nameOf(layer).isNormal() + ), + endpointName + ); + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/InstanceCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/InstanceCondition.java new file mode 100644 index 0000000000..3784d7cf10 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/InstanceCondition.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.query.input; + +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.apache.skywalking.oap.server.core.analysis.IDManager; +import org.apache.skywalking.oap.server.core.analysis.Layer; + +@Setter +@Getter +@ToString +public class InstanceCondition { + private String serviceName; + private String instanceName; + @Nullable + private String layer; + + /** + * Get the instance ID based on the service name, instance name and {@link Layer} name. + * The layer can be null, in which case it defaults to a normal layer. + * Otherwise, it uses the provided layer to determine if the service is normal or not. + * The un-normal layer includes VIRTUAL_DATABASE/VIRTUAL_MQ/VIRTUAL_GATEWAY, etc. + * @return instance ID + */ + public String getInstanceId() { + // default to true if service layer is not provided + return IDManager.ServiceInstanceID.buildId( + IDManager.ServiceID.buildId( + serviceName, + layer == null || Layer.nameOf(layer).isNormal() + ), + instanceName + ); + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/LogQueryConditionByName.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/LogQueryConditionByName.java new file mode 100644 index 0000000000..5e53596672 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/LogQueryConditionByName.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.query.input; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag; +import org.apache.skywalking.oap.server.core.query.enumeration.Order; +import org.apache.skywalking.oap.server.core.query.type.Pagination; + +@Getter +@Setter +@ToString +public class LogQueryConditionByName { + private ServiceCondition service; + private InstanceCondition instance; + private EndpointCondition endpoint; + private TraceScopeCondition relatedTrace; + private Duration queryDuration; + private Pagination paging; + private List<Tag> tags; + private List<String> keywordsOfContent; + private List<String> excludingKeywordsOfContent; + private Order queryOrder; + + public String getServiceId() { + if (service != null) { + return service.getServiceId(); + } else { + return null; + } + } + + public String getServiceInstanceId() { + if (instance != null) { + return instance.getInstanceId(); + } else { + return null; + } + } + + public String getEndpointId() { + if (endpoint != null) { + return endpoint.getEndpointId(); + } else { + return null; + } + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/ServiceCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/ServiceCondition.java new file mode 100644 index 0000000000..a4312ee425 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/ServiceCondition.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.query.input; + +import javax.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.apache.skywalking.oap.server.core.analysis.IDManager; +import org.apache.skywalking.oap.server.core.analysis.Layer; + +@Setter +@Getter +@ToString +public class ServiceCondition { + private String serviceName; + @Nullable + private String layer; + + /** + * Get the service ID based on the service name and {@link Layer} name. + * The layer can be null, in which case it defaults to a normal layer. + * Otherwise, it uses the provided layer to determine if the service is normal or not. + * The un-normal layer includes VIRTUAL_DATABASE/VIRTUAL_MQ/VIRTUAL_GATEWAY, etc. + * @return service ID + */ + public String getServiceId() { + // default to true if service layer is not provided + return IDManager.ServiceID.buildId(serviceName, layer == null || Layer.nameOf(layer).isNormal()); + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryConditionByName.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryConditionByName.java new file mode 100644 index 0000000000..7a340aa499 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryConditionByName.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.query.input; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag; +import org.apache.skywalking.oap.server.core.query.type.Pagination; +import org.apache.skywalking.oap.server.core.query.type.QueryOrder; +import org.apache.skywalking.oap.server.core.query.type.TraceState; + +@Getter +@Setter +@ToString +public class TraceQueryConditionByName { + private ServiceCondition service; + private InstanceCondition instance; + private EndpointCondition endpoint; + private String traceId; + private Duration queryDuration; + private int minTraceDuration; + private int maxTraceDuration; + private TraceState traceState; + private QueryOrder queryOrder; + private Pagination paging; + private List<Tag> tags; + + public String getServiceId() { + if (service != null) { + return service.getServiceId(); + } else { + return null; + } + } + + public String getServiceInstanceId() { + if (instance != null) { + return instance.getInstanceId(); + } else { + return null; + } + } + + public String getEndpointId() { + if (endpoint != null) { + return endpoint.getEndpointId(); + } else { + return null; + } + } +} diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java index 3b077aff39..eb725bc8a1 100644 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/LogQuery.java @@ -30,6 +30,7 @@ import org.apache.skywalking.oap.server.core.query.TagAutoCompleteQueryService; import org.apache.skywalking.oap.server.core.query.enumeration.Order; import org.apache.skywalking.oap.server.core.query.input.Duration; import org.apache.skywalking.oap.server.core.query.input.LogQueryCondition; +import org.apache.skywalking.oap.server.core.query.input.LogQueryConditionByName; import org.apache.skywalking.oap.server.core.query.type.Logs; import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan; import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext; @@ -88,6 +89,38 @@ public class LogQuery implements GraphQLQueryResolver { }); } + public CompletableFuture<Logs> queryLogsByName(LogQueryConditionByName condition, boolean debug) { + return queryAsync(() -> { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "LogQueryConditionByName: " + condition, debug, false); + DebuggingTraceContext.TRACE_CONTEXT.set(traceContext); + DebuggingSpan span = traceContext.createSpan("Query logs"); + try { + LogQueryCondition logQueryCondition = new LogQueryCondition(); + logQueryCondition.setServiceId(condition.getServiceId()); + logQueryCondition.setServiceInstanceId(condition.getServiceInstanceId()); + logQueryCondition.setEndpointId(condition.getEndpointId()); + logQueryCondition.setRelatedTrace(condition.getRelatedTrace()); + logQueryCondition.setQueryDuration(condition.getQueryDuration()); + logQueryCondition.setPaging(condition.getPaging()); + logQueryCondition.setTags(condition.getTags()); + logQueryCondition.setKeywordsOfContent(condition.getKeywordsOfContent()); + logQueryCondition.setExcludingKeywordsOfContent(condition.getExcludingKeywordsOfContent()); + logQueryCondition.setQueryOrder(condition.getQueryOrder()); + + Logs logs = invokeQueryLogs(logQueryCondition); + if (debug) { + logs.setDebuggingTrace(traceContext.getExecTrace()); + } + return logs; + } finally { + traceContext.stopSpan(span); + traceContext.stopTrace(); + TRACE_CONTEXT.remove(); + } + }); + } + private Logs invokeQueryLogs(LogQueryCondition condition) throws IOException { if (isNull(condition.getQueryDuration()) && isNull(condition.getRelatedTrace())) { throw new UnexpectedException("The condition must contains either queryDuration or relatedTrace."); diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQueryV2.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQueryV2.java index d393a39751..c300fb5e52 100644 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQueryV2.java +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetadataQueryV2.java @@ -30,6 +30,7 @@ import org.apache.skywalking.oap.server.core.analysis.IDManager; import org.apache.skywalking.oap.server.core.query.MetadataQueryService; import org.apache.skywalking.oap.server.core.query.TTLStatusQuery; import org.apache.skywalking.oap.server.core.query.input.Duration; +import org.apache.skywalking.oap.server.core.query.input.ServiceCondition; import org.apache.skywalking.oap.server.core.query.type.Endpoint; import org.apache.skywalking.oap.server.core.query.type.EndpointInfo; import org.apache.skywalking.oap.server.core.query.type.Process; @@ -95,6 +96,11 @@ public class MetadataQueryV2 implements GraphQLQueryResolver { return queryAsync(() -> getMetadataQueryService().listInstances(duration, serviceId)); } + public CompletableFuture<List<ServiceInstance>> listInstancesByName(final Duration duration, + final ServiceCondition service) { + return queryAsync(() -> getMetadataQueryService().listInstances(duration, service.getServiceId())); + } + public CompletableFuture<ServiceInstance> getInstance(final String instanceId) { return queryAsync(() -> getMetadataQueryService().getInstance(instanceId)); } @@ -104,6 +110,12 @@ public class MetadataQueryV2 implements GraphQLQueryResolver { return queryAsync(() -> getMetadataQueryService().findEndpoint(keyword, serviceId, limit, duration)); } + public CompletableFuture<List<Endpoint>> findEndpointByName(final String keyword, final ServiceCondition service, + final int limit, final Duration duration) { + return queryAsync( + () -> getMetadataQueryService().findEndpoint(keyword, service.getServiceId(), limit, duration)); + } + public CompletableFuture<EndpointInfo> getEndpointInfo(final String endpointId) { return queryAsync(() -> getMetadataQueryService().getEndpointInfo(endpointId)); } 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 5df8d7b630..52b8ef455a 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 @@ -25,6 +25,9 @@ import java.util.concurrent.CompletableFuture; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.query.TopologyQueryService; import org.apache.skywalking.oap.server.core.query.input.Duration; +import org.apache.skywalking.oap.server.core.query.input.EndpointCondition; +import org.apache.skywalking.oap.server.core.query.input.InstanceCondition; +import org.apache.skywalking.oap.server.core.query.input.ServiceCondition; 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; @@ -96,6 +99,28 @@ public class TopologyQuery implements GraphQLQueryResolver { } } + public Topology getServiceTopologyByName(final ServiceCondition service, + final Duration duration, + final boolean debug) { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "Service: " + service + "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(service.getServiceId()); + Topology topology = this.getServicesTopology(selectedServiceList, duration, debug).join(); + if (debug) { + topology.setDebuggingTrace(traceContext.getExecTrace()); + } + return topology; + } finally { + traceContext.stopSpan(span); + traceContext.stopTrace(); + TRACE_CONTEXT.remove(); + } + } + public CompletableFuture<Topology> getServicesTopology(final List<String> serviceIds, final Duration duration, final boolean debug) { @@ -118,6 +143,32 @@ public class TopologyQuery implements GraphQLQueryResolver { }); } + public CompletableFuture<Topology> getServicesTopologyByNames(final List<ServiceCondition> services, + final Duration duration, + final boolean debug) { + return queryAsync(() -> { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "Services: " + services + "Duration: " + duration, debug, false); + DebuggingTraceContext.TRACE_CONTEXT.set(traceContext); + DebuggingSpan span = traceContext.createSpan("Query service topology"); + try { + List<String> serviceIds = new ArrayList<>(services.size()); + for (ServiceCondition service : services) { + serviceIds.add(service.getServiceId()); + } + Topology topology = getQueryService().getServiceTopology(duration, serviceIds); + if (debug) { + topology.setDebuggingTrace(traceContext.getExecTrace()); + } + return topology; + } finally { + traceContext.stopSpan(span); + traceContext.stopTrace(); + TRACE_CONTEXT.remove(); + } + }); + } + public CompletableFuture<ServiceInstanceTopology> getServiceInstanceTopology(final String clientServiceId, final String serverServiceId, final Duration duration, @@ -146,6 +197,34 @@ public class TopologyQuery implements GraphQLQueryResolver { }); } + public CompletableFuture<ServiceInstanceTopology> getServiceInstanceTopologyByName(final ServiceCondition clientService, + final ServiceCondition serverService, + final Duration duration, + final boolean debug) { + return queryAsync(() -> { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "ClientService: " + clientService + ", ServerService: " + serverService + ", Duration: " + duration, + debug, false + ); + DebuggingTraceContext.TRACE_CONTEXT.set(traceContext); + DebuggingSpan span = traceContext.createSpan("Query service instance topology"); + try { + ServiceInstanceTopology topology = getQueryService().getServiceInstanceTopology( + clientService.getServiceId(), serverService.getServiceId(), + duration + ); + if (debug) { + topology.setDebuggingTrace(traceContext.getExecTrace()); + } + return topology; + } finally { + traceContext.stopSpan(span); + traceContext.stopTrace(); + TRACE_CONTEXT.remove(); + } + }); + } + /** * Replaced by {@link #getEndpointDependencies(String, Duration, boolean)} */ @@ -176,6 +255,29 @@ public class TopologyQuery implements GraphQLQueryResolver { }); } + public CompletableFuture<EndpointTopology> getEndpointDependenciesByName(final EndpointCondition endpoint, + final Duration duration, + final boolean debug) { + return queryAsync(() -> { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "Endpoint: " + endpoint + ", " + + "Duration: " + duration, debug, false); + DebuggingTraceContext.TRACE_CONTEXT.set(traceContext); + DebuggingSpan span = traceContext.createSpan("Query endpoint dependencies"); + try { + EndpointTopology topology = getQueryService().getEndpointDependencies(duration, endpoint.getEndpointId()); + if (debug) { + topology.setDebuggingTrace(traceContext.getExecTrace()); + } + return topology; + } finally { + traceContext.stopSpan(span); + traceContext.stopTrace(); + TRACE_CONTEXT.remove(); + } + }); + } + public CompletableFuture<ProcessTopology> getProcessTopology(final String instanceId, final Duration duration, final boolean debug) { return queryAsync(() -> { DebuggingTraceContext traceContext = new DebuggingTraceContext( @@ -195,4 +297,26 @@ public class TopologyQuery implements GraphQLQueryResolver { } }); } + + public CompletableFuture<ProcessTopology> getProcessTopologyByName(final InstanceCondition instance, + final Duration duration, final boolean debug) { + return queryAsync(() -> { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "Instance: " + instance + ", " + + "Duration: " + duration, debug, false); + DebuggingTraceContext.TRACE_CONTEXT.set(traceContext); + DebuggingSpan span = traceContext.createSpan("Query process topology"); + try { + ProcessTopology topology = getQueryService().getProcessTopology(instance.getInstanceId(), 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/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java index 829405fb03..d5efaabcc7 100644 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java @@ -31,6 +31,7 @@ import org.apache.skywalking.oap.server.core.query.TagAutoCompleteQueryService; import org.apache.skywalking.oap.server.core.query.TraceQueryService; import org.apache.skywalking.oap.server.core.query.input.Duration; import org.apache.skywalking.oap.server.core.query.input.TraceQueryCondition; +import org.apache.skywalking.oap.server.core.query.input.TraceQueryConditionByName; import org.apache.skywalking.oap.server.core.query.type.Pagination; import org.apache.skywalking.oap.server.core.query.type.QueryOrder; import org.apache.skywalking.oap.server.core.query.type.Trace; @@ -88,6 +89,39 @@ public class TraceQuery implements GraphQLQueryResolver { }); } + public CompletableFuture<TraceBrief> queryBasicTracesByName(final TraceQueryConditionByName condition, boolean debug) { + return queryAsync(() -> { + DebuggingTraceContext traceContext = new DebuggingTraceContext( + "TraceQueryCondition: " + condition, debug, false); + DebuggingTraceContext.TRACE_CONTEXT.set(traceContext); + DebuggingSpan span = traceContext.createSpan("Query basic traces"); + try { + TraceQueryCondition traceQueryCondition = new TraceQueryCondition(); + traceQueryCondition.setServiceId(condition.getServiceId()); + traceQueryCondition.setServiceInstanceId(condition.getServiceInstanceId()); + traceQueryCondition.setEndpointId(condition.getEndpointId()); + traceQueryCondition.setTraceId(condition.getTraceId()); + traceQueryCondition.setQueryDuration(condition.getQueryDuration()); + traceQueryCondition.setMinTraceDuration(condition.getMinTraceDuration()); + traceQueryCondition.setMaxTraceDuration(condition.getMaxTraceDuration()); + traceQueryCondition.setTraceState(condition.getTraceState()); + traceQueryCondition.setQueryOrder(condition.getQueryOrder()); + traceQueryCondition.setPaging(condition.getPaging()); + traceQueryCondition.setTags(condition.getTags()); + + TraceBrief traceBrief = invokeQueryBasicTraces(traceQueryCondition); + if (debug) { + traceBrief.setDebuggingTrace(traceContext.getExecTrace()); + } + return traceBrief; + } finally { + traceContext.stopSpan(span); + traceContext.stopTrace(); + TRACE_CONTEXT.remove(); + } + }); + } + private TraceBrief invokeQueryBasicTraces(final TraceQueryCondition condition) throws IOException { String traceId = Const.EMPTY_STRING; 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 e6d2b99597..abf4c4d158 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 e6d2b99597a6489ab58f8a2ff32f212c8ef9b388 +Subproject commit abf4c4d1588d16facae4a696032d5f8b68a4ccaf diff --git a/test/e2e-v2/cases/gateway/docker-compose.yml b/test/e2e-v2/cases/gateway/docker-compose.yml index d5dcf54cf0..0ebaf48123 100644 --- a/test/e2e-v2/cases/gateway/docker-compose.yml +++ b/test/e2e-v2/cases/gateway/docker-compose.yml @@ -28,20 +28,10 @@ services: timeout: 60s retries: 120 - es: - image: elastic/elasticsearch:6.3.2 - expose: - - 9200 - networks: - - e2e - environment: - - discovery.type=single-node - - cluster.routing.allocation.disk.threshold_enabled=false - healthcheck: - test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9200"] - interval: 5s - timeout: 60s - retries: 120 + banyandb: + extends: + file: ../../script/docker-compose/base-compose.yml + service: banyandb oap1: extends: @@ -49,13 +39,12 @@ services: service: oap environment: SW_CLUSTER: zookeeper - SW_STORAGE: elasticsearch volumes: - ./gateways.yml:/skywalking/config/gateways.yml depends_on: zk: condition: service_healthy - es: + banyandb: condition: service_healthy oap2: @@ -64,13 +53,12 @@ services: service: oap environment: SW_CLUSTER: zookeeper - SW_STORAGE: elasticsearch volumes: - ./gateways.yml:/skywalking/config/gateways.yml depends_on: zk: condition: service_healthy - es: + banyandb: condition: service_healthy oap1: condition: service_healthy