in oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/HierarchyQueryService.java [213:324]
public InstanceHierarchy getInstanceHierarchy(String instanceId, String layer) throws Exception {
if (!this.isEnableHierarchy) {
log.warn("CoreModuleConfig config {enableHierarchy} is false, return empty InstanceHierarchy.");
return new InstanceHierarchy();
}
ServiceInstance self = getMetadataQueryDAO().getInstance(instanceId);
if (self == null) {
return new InstanceHierarchy();
}
List<HierarchyInstanceRelation> relations = new ArrayList<>();
//build from service hierarchy and instance traffic
IDManager.ServiceInstanceID.InstanceIDDefinition idDefinition = IDManager.ServiceInstanceID.analysisId(
instanceId);
IDManager.ServiceID.ServiceIDDefinition serviceIdDefinition = IDManager.ServiceID.analysisId(
idDefinition.getServiceId());
//instance is only query 1 depth of service hierarchy, set max depth to 1
ServiceHierarchy serviceHierarchy = getServiceHierarchy(idDefinition.getServiceId(), layer, 1, HierarchyDirection.All);
Optional<Attribute> host = self.getAttributes()
.stream()
.filter(hostAttrFilter())
.findFirst();
Optional<ServiceInstance> lower;
Optional<ServiceInstance> upper;
for (HierarchyServiceRelation serviceRelation : serviceHierarchy.getRelations()) {
//if the service relation is lower/upper, then the instance relation is upper/lower
List<ServiceInstance> lowerCandidates = getMetadataQueryDAO().listInstances(
null,
serviceRelation.getLowerService()
.getId()
);
List<ServiceInstance> upperCandidates = getMetadataQueryDAO().listInstances(
null,
serviceRelation.getUpperService()
.getId()
);
lower = lowerCandidates.stream()
.filter(relatedInstanceFilter(self, host))
.findFirst();
upper = upperCandidates.stream()
.filter(relatedInstanceFilter(self, host))
.findFirst();
HierarchyRelatedInstance instance = new HierarchyRelatedInstance();
instance.setId(self.getId());
instance.setName(self.getName());
instance.setServiceId(idDefinition.getServiceId());
instance.setServiceName(serviceIdDefinition.getName());
instance.setNormal(serviceIdDefinition.isReal());
instance.setLayer(layer);
//The instances could be same but the service layer is different
if (lower.isPresent() && !layer.equals(serviceRelation.getLowerService().getLayer())) {
HierarchyRelatedInstance relatedInstance = new HierarchyRelatedInstance();
relatedInstance.setId(lower.get().getId());
relatedInstance.setName(lower.get().getName());
relatedInstance.setServiceId(serviceRelation.getLowerService().getId());
relatedInstance.setServiceName(serviceRelation.getLowerService().getName());
relatedInstance.setLayer(serviceRelation.getLowerService().getLayer());
relatedInstance.setNormal(serviceRelation.getLowerService().isNormal());
relations.add(new HierarchyInstanceRelation(instance, relatedInstance));
}
if (upper.isPresent() && !layer.equals(serviceRelation.getUpperService().getLayer())) {
HierarchyRelatedInstance relatedInstance = new HierarchyRelatedInstance();
relatedInstance.setId(upper.get().getId());
relatedInstance.setName(upper.get().getName());
relatedInstance.setServiceId(serviceRelation.getUpperService().getId());
relatedInstance.setServiceName(serviceRelation.getUpperService().getName());
relatedInstance.setLayer(serviceRelation.getUpperService().getLayer());
relatedInstance.setNormal(serviceRelation.getUpperService().isNormal());
relations.add(new HierarchyInstanceRelation(relatedInstance, instance));
}
}
//build from storage directly
List<InstanceHierarchyRelationTraffic> traffics = getHierarchyQueryDAO().readInstanceHierarchyRelations(
instanceId, layer);
for (InstanceHierarchyRelationTraffic traffic : traffics) {
HierarchyRelatedInstance instance = new HierarchyRelatedInstance();
IDManager.ServiceInstanceID.InstanceIDDefinition idDef = IDManager.ServiceInstanceID.analysisId(
instanceId);
IDManager.ServiceID.ServiceIDDefinition serviceIdDef = IDManager.ServiceID.analysisId(
idDefinition.getServiceId());
instance.setId(traffic.getInstanceId());
instance.setName(idDef.getName());
instance.setServiceId(idDef.getServiceId());
instance.setServiceName(serviceIdDef.getName());
instance.setLayer(traffic.getServiceLayer().name());
instance.setNormal(serviceIdDef.isReal());
HierarchyRelatedInstance relatedInstance = new HierarchyRelatedInstance();
IDManager.ServiceInstanceID.InstanceIDDefinition relatedIdDef = IDManager.ServiceInstanceID.analysisId(
traffic.getRelatedInstanceId());
IDManager.ServiceID.ServiceIDDefinition relatedServiceIdDef = IDManager.ServiceID.analysisId(
relatedIdDef.getServiceId());
relatedInstance.setId(traffic.getRelatedInstanceId());
relatedInstance.setName(relatedIdDef.getName());
relatedInstance.setServiceId(relatedIdDef.getServiceId());
relatedInstance.setServiceName(relatedServiceIdDef.getName());
relatedInstance.setLayer(traffic.getRelatedServiceLayer().name());
relatedInstance.setNormal(relatedServiceIdDef.isReal());
Map<String, HierarchyDefinitionService.MatchingRule> lowerLayers = getHierarchyDefinition().get(
traffic.getServiceLayer().name());
if (lowerLayers != null && lowerLayers.containsKey(traffic.getRelatedServiceLayer().name())) {
relations.add(new HierarchyInstanceRelation(instance, relatedInstance));
}
}
InstanceHierarchy hierarchy = new InstanceHierarchy();
hierarchy.setRelations(relations.stream().distinct().collect(Collectors.toList()));
return hierarchy;
}