blob: eca8f0f2a655a41de1caea10ecfb007abb659ad6 [file] [log] [blame]
/*
* 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.graphql.resolver;
import graphql.kickstart.tools.GraphQLQueryResolver;
import graphql.schema.DataFetchingEnvironment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.EventQueryService;
import org.apache.skywalking.oap.server.core.query.enumeration.Scope;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.AlarmMessage;
import org.apache.skywalking.oap.server.core.query.type.AlarmTrend;
import org.apache.skywalking.oap.server.core.query.type.Alarms;
import org.apache.skywalking.oap.server.core.query.type.Pagination;
import org.apache.skywalking.oap.server.core.query.type.event.Event;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Source;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static org.apache.skywalking.oap.server.library.util.CollectionUtils.isNotEmpty;
public class AlarmQuery implements GraphQLQueryResolver {
private final ModuleManager moduleManager;
private AlarmQueryService queryService;
private EventQueryService eventQueryService;
public AlarmQuery(ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
private AlarmQueryService getQueryService() {
if (queryService == null) {
this.queryService = moduleManager.find(CoreModule.NAME).provider().getService(AlarmQueryService.class);
}
return queryService;
}
private EventQueryService getEventQueryService() {
if (eventQueryService == null) {
this.eventQueryService = moduleManager.find(CoreModule.NAME).provider().getService(EventQueryService.class);
}
return eventQueryService;
}
public AlarmTrend getAlarmTrend(final Duration duration) {
return new AlarmTrend();
}
public Alarms getAlarm(final Duration duration, final Scope scope, final String keyword,
final Pagination paging, final List<Tag> tags,
final DataFetchingEnvironment env) throws Exception {
Integer scopeId = null;
if (scope != null) {
scopeId = scope.getScopeId();
}
final EventQueryCondition.EventQueryConditionBuilder conditionPrototype =
EventQueryCondition.builder()
.paging(new Pagination(1, IEventQueryDAO.MAX_SIZE));
if (nonNull(duration)) {
conditionPrototype.time(duration);
}
Alarms alarms = getQueryService().getAlarm(
scopeId, keyword, paging, duration, tags);
final boolean selectEvents = env.getSelectionSet().contains("**/events/**");
if (selectEvents) {
return findRelevantEvents(alarms, conditionPrototype);
}
return alarms;
}
private Alarms findRelevantEvents(
final Alarms alarms,
final EventQueryCondition.EventQueryConditionBuilder conditionPrototype
) throws Exception {
if (CollectionUtils.isEmpty(alarms.getMsgs())) {
return alarms;
}
final List<EventQueryCondition> allConditions =
alarms.getMsgs()
.stream()
.flatMap(m -> buildEventSources(m).stream().map(conditionPrototype::source))
.map(EventQueryCondition.EventQueryConditionBuilder::build)
.collect(Collectors.toList());
final List<Event> events = getEventQueryService().queryEvents(allConditions).getEvents();
final Map<String, List<Event>> eventsKeyedBySourceId =
events.stream()
.filter(it -> !isNullOrEmpty(buildSourceID(it)))
.collect(Collectors.groupingBy(this::buildSourceID));
alarms.getMsgs().forEach(a -> {
if (isNotEmpty(eventsKeyedBySourceId.get(a.getId()))) {
a.getEvents().addAll(eventsKeyedBySourceId.get(a.getId()));
}
if (isNotEmpty(eventsKeyedBySourceId.get(a.getId1()))) {
a.getEvents().addAll(eventsKeyedBySourceId.get(a.getId1()));
}
});
return alarms;
}
private List<Source> buildEventSources(AlarmMessage msg) {
final List<Source> sources = new ArrayList<>(2);
final Source.SourceBuilder sourcePrototype = Source.builder();
switch (msg.getScopeId()) {
case DefaultScopeDefine.SERVICE_RELATION:
final IDManager.ServiceID.ServiceIDDefinition destServiceIdDef = IDManager.ServiceID.analysisId(msg.getId1());
sources.add(sourcePrototype.service(destServiceIdDef.getName()).build());
// fall through
case DefaultScopeDefine.SERVICE:
final IDManager.ServiceID.ServiceIDDefinition sourceServiceIdDef = IDManager.ServiceID.analysisId(msg.getId());
sources.add(sourcePrototype.service(sourceServiceIdDef.getName()).build());
break;
case DefaultScopeDefine.SERVICE_INSTANCE_RELATION:
final IDManager.ServiceInstanceID.InstanceIDDefinition destInstanceIdDef = IDManager.ServiceInstanceID.analysisId(msg.getId1());
final String destServiceName = IDManager.ServiceID.analysisId(destInstanceIdDef.getServiceId()).getName();
sources.add(sourcePrototype.service(destServiceName).serviceInstance(destInstanceIdDef.getName()).build());
// fall through
case DefaultScopeDefine.SERVICE_INSTANCE:
final IDManager.ServiceInstanceID.InstanceIDDefinition sourceInstanceIdDef = IDManager.ServiceInstanceID.analysisId(msg.getId());
final String serviceName = IDManager.ServiceID.analysisId(sourceInstanceIdDef.getServiceId()).getName();
sources.add(sourcePrototype.serviceInstance(sourceInstanceIdDef.getName()).service(serviceName).build());
break;
case DefaultScopeDefine.ENDPOINT_RELATION:
final IDManager.EndpointID.EndpointIDDefinition destEndpointIDDef = IDManager.EndpointID.analysisId(msg.getId1());
final String destEndpointServiceName = IDManager.ServiceID.analysisId(destEndpointIDDef.getServiceId()).getName();
sources.add(sourcePrototype.service(destEndpointServiceName).build());
// fall through
case DefaultScopeDefine.ENDPOINT:
final IDManager.EndpointID.EndpointIDDefinition endpointIDDef = IDManager.EndpointID.analysisId(msg.getId());
final String endpointServiceName = IDManager.ServiceID.analysisId(endpointIDDef.getServiceId()).getName();
sources.add(sourcePrototype.service(endpointServiceName).build());
break;
}
return sources;
}
protected String buildSourceID(final Event event) {
final Source source = event.getSource();
if (isNull(source)) {
return "";
}
final String service = source.getService();
final String serviceId = IDManager.ServiceID.buildId(service, true);
if (isNullOrEmpty(service)) {
return "";
}
final String instance = source.getServiceInstance();
if (isNullOrEmpty(instance)) {
return serviceId;
}
return IDManager.ServiceInstanceID.buildId(serviceId, instance);
}
}