Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion docs/en/api/query-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
```

Expand Down Expand Up @@ -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
Expand All @@ -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.
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 @@ -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

Expand Down
9 changes: 8 additions & 1 deletion docs/en/debugging/query-tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}`.
Expand Down Expand Up @@ -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
...
Expand Down Expand Up @@ -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
}
```

Expand Down Expand Up @@ -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
...
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public List<Service> listServices(final String layer, final String group) throws
}

@SneakyThrows
public Service getService(final String serviceId) throws IOException {
public Service getService(final String serviceId) {
final List<Service> services = this.combineServices(this.serviceCache.get(true).get(serviceId));
return CollectionUtils.isNotEmpty(services) ? services.get(0) : null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import org.apache.skywalking.oap.server.library.module.Service;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -130,10 +129,16 @@ public Topology getServiceTopology(final Duration duration,
span = traceContext.createSpan("Query Service: getServiceTopology");
span.setMsg("Duration: " + duration + ", ServiceIds: " + serviceIds);
}
if (CollectionUtils.isEmpty(serviceIds)) {
//check if the service exists, the unreal service do not check
List<String> ids = serviceIds.stream()
.filter(id -> getMetadataQueryService().getService(id) != null ||
!IDManager.ServiceID.analysisId(id).isReal())
.collect(Collectors.toList());

if (CollectionUtils.isEmpty(ids)) {
return new Topology();
}
return invokeGetServiceTopology(duration, serviceIds);
return invokeGetServiceTopology(duration, ids);
} finally {
if (traceContext != null && span != null) {
traceContext.stopSpan(span);
Expand Down Expand Up @@ -193,6 +198,17 @@ public ServiceInstanceTopology getServiceInstanceTopology(final String clientSer
span = traceContext.createSpan("Query Service: getServiceInstanceTopology");
span.setMsg("ClientServiceId: " + clientServiceId + ", ServerServiceId: " + serverServiceId + ", Duration: " + duration);
}
//check if the service exists, the unreal service do not check
if (getMetadataQueryService().getService(clientServiceId) == null &&
IDManager.ServiceID.analysisId(clientServiceId).isReal()) {
return new ServiceInstanceTopology();
}

if (getMetadataQueryService().getService(serverServiceId) == null &&
IDManager.ServiceID.analysisId(serverServiceId).isReal()) {
return new ServiceInstanceTopology();
}

return invokeGetServiceInstanceTopology(clientServiceId, serverServiceId, duration);
} finally {
if (traceContext != null && span != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
);
}
}
Original file line number Diff line number Diff line change
@@ -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
);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Loading
Loading