From bb590daba99e25e78c98a9601fae46e63fc5efa6 Mon Sep 17 00:00:00 2001 From: chen~ Date: Wed, 19 May 2021 14:14:48 +0800 Subject: [PATCH] Include event(s) to alarms. (#6888) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kezhenxu94 Co-authored-by: 吴晟 Wu Sheng --- CHANGES.md | 1 + .../server/core/query/EventQueryService.java | 11 ++ .../server/core/query/type/AlarmMessage.java | 3 + .../server/core/query/type/event/Event.java | 1 - .../query/type/event/EventQueryCondition.java | 6 + .../server/core/query/type/event/Source.java | 2 + .../core/storage/query/IEventQueryDAO.java | 4 + .../query/graphql/resolver/AlarmQuery.java | 127 +++++++++++++- .../src/main/resources/query-protocol | 2 +- .../elasticsearch/query/AlarmQueryEsDAO.java | 1 + .../elasticsearch/query/ESEventQueryDAO.java | 61 +++++-- .../query/AlarmQueryEs7DAO.java | 1 + .../query/ES7EventQueryDAO.java | 18 +- .../plugin/influxdb/query/EventQueryDAO.java | 164 ++++++++++++++---- .../plugin/jdbc/h2/dao/H2AlarmQueryDAO.java | 1 + .../plugin/jdbc/h2/dao/H2EventQueryDAO.java | 141 ++++++++++----- .../apache/skywalking/e2e/AbstractQuery.java | 15 ++ .../apache/skywalking/e2e/alarm/Alarm.java | 2 + .../skywalking/e2e/alarm/AlarmMatcher.java | 24 ++- .../skywalking/e2e/alarm/AlarmQuery.java | 21 +++ .../src/main/resources/read-alarms.gql | 13 ++ .../apache/skywalking/e2e/alarm/AlarmE2E.java | 5 +- .../alarm/silence-after-graphql-critical.yml | 7 +- .../alarm/silence-after-graphql-warn.yml | 6 + .../alarm/silence-before-graphql-critical.yml | 3 + .../alarm/silence-before-graphql-warn.yml | 3 + 26 files changed, 529 insertions(+), 114 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3c390680bf..848fb49cb6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -45,6 +45,7 @@ Release Notes. * Fix: NPE when configmap has no data. * Fix: Dynamic Configuration key `slowTraceSegmentThreshold` not work * Fix: `!=` is not supported in oal when parameters are numbers. +* Include events of the entity(s) in the alarm. #### UI * Add logo for kong plugin. diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EventQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EventQueryService.java index a489fde4aa..7fc20e9331 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EventQueryService.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/EventQueryService.java @@ -26,6 +26,9 @@ 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.module.Service; +import java.util.List; +import java.util.Objects; + import static java.util.Objects.isNull; import static org.apache.skywalking.apm.util.StringUtil.isBlank; @@ -53,6 +56,14 @@ public class EventQueryService implements Service { return getDao().queryEvents(condition); } + public Events queryEvents(final List conditions) throws Exception { + EventQueryCondition condition = conditions.stream().filter(c -> isBlank(c.getUuid()) && isDurationInvalid(c.getTime())).findFirst().orElse(null); + if (Objects.nonNull(condition)) { + throw new IllegalArgumentException("time field is required when uuid is absent."); + } + return getDao().queryEvents(conditions); + } + boolean isDurationInvalid(final Duration duration) { return isNull(duration) || (isBlank(duration.getStart()) || isBlank(duration.getEnd())); } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java index 328a985141..8608c86ef0 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/AlarmMessage.java @@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.query.type; import lombok.Getter; import lombok.Setter; import org.apache.skywalking.oap.server.core.query.enumeration.Scope; +import org.apache.skywalking.oap.server.core.query.type.event.Event; import java.util.ArrayList; import java.util.List; @@ -33,7 +34,9 @@ public class AlarmMessage { private String id; private String message; private Long startTime; + private transient String id1; private final List tags; + private List events = new ArrayList<>(2); public AlarmMessage() { tags = new ArrayList<>(); diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Event.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Event.java index 7b2d17e60a..c045310e29 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Event.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Event.java @@ -58,5 +58,4 @@ public class Event { this.parameters = map.entrySet().stream().map(e -> new KeyValue(e.getKey(), e.getValue())).collect(Collectors.toList()); } } - } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/EventQueryCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/EventQueryCondition.java index 30009a85c4..a90e08b19c 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/EventQueryCondition.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/EventQueryCondition.java @@ -18,7 +18,10 @@ package org.apache.skywalking.oap.server.core.query.type.event; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import org.apache.skywalking.oap.server.core.query.enumeration.Order; import org.apache.skywalking.oap.server.core.query.input.Duration; @@ -26,6 +29,9 @@ import static org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO import static org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO.MAX_SIZE; @Data +@AllArgsConstructor +@NoArgsConstructor +@Builder(toBuilder = true) public class EventQueryCondition { private String uuid; diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Source.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Source.java index 98dd2b75eb..0c08e3bfa5 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Source.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/event/Source.java @@ -19,10 +19,12 @@ package org.apache.skywalking.oap.server.core.query.type.event; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data +@Builder @NoArgsConstructor @AllArgsConstructor public class Source { diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IEventQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IEventQueryDAO.java index e377226e23..ea09a4d620 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IEventQueryDAO.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IEventQueryDAO.java @@ -22,9 +22,13 @@ import org.apache.skywalking.oap.server.core.query.type.event.EventQueryConditio import org.apache.skywalking.oap.server.core.query.type.event.Events; import org.apache.skywalking.oap.server.core.storage.DAO; +import java.util.List; + public interface IEventQueryDAO extends DAO { int DEFAULT_SIZE = 20; int MAX_SIZE = 100; Events queryEvents(final EventQueryCondition condition) throws Exception; + + Events queryEvents(final List conditionList) throws Exception; } diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java index 9bac9cb569..c0d38f45af 100644 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/AlarmQuery.java @@ -19,26 +19,43 @@ package org.apache.skywalking.oap.query.graphql.resolver; import com.coxautodev.graphql.tools.GraphQLQueryResolver; -import java.io.IOException; + +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 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; } @@ -50,23 +67,125 @@ public class AlarmQuery implements GraphQLQueryResolver { 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 tags) throws IOException { + final Pagination paging, final List tags) throws Exception { Integer scopeId = null; if (scope != null) { scopeId = scope.getScopeId(); } long startSecondTB = 0; long endSecondTB = 0; + final EventQueryCondition.EventQueryConditionBuilder conditionPrototype = EventQueryCondition.builder().size(IEventQueryDAO.MAX_SIZE); if (nonNull(duration)) { startSecondTB = duration.getStartTimeBucketInSec(); endSecondTB = duration.getEndTimeBucketInSec(); + conditionPrototype.time(duration); } - return getQueryService().getAlarm( + Alarms alarms = getQueryService().getAlarm( scopeId, keyword, paging, startSecondTB, endSecondTB, tags); + return findRelevantEvents(alarms, conditionPrototype); + } + + private Alarms findRelevantEvents( + final Alarms alarms, + final EventQueryCondition.EventQueryConditionBuilder conditionPrototype + ) throws Exception { + + if (alarms.getTotal() < 1) { + return alarms; + } + + final List allConditions = + alarms.getMsgs() + .stream() + .flatMap(m -> buildEventSources(m).stream().map(conditionPrototype::source)) + .map(EventQueryCondition.EventQueryConditionBuilder::build) + .collect(Collectors.toList()); + + final List events = getEventQueryService().queryEvents(allConditions).getEvents(); + final Map> 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 buildEventSources(AlarmMessage msg) { + final List 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(); + if (isNullOrEmpty(service)) { + return ""; + } + + final String instance = source.getServiceInstance(); + if (isNullOrEmpty(instance)) { + return IDManager.ServiceID.buildId(service, true); + } + + return IDManager.ServiceInstanceID.buildId(service, instance); } } 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 0c2388ba18..84c635180b 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 0c2388ba18cfc1b1b103ddad71f9765bd21dff6e +Subproject commit 84c635180b8dde4210865f655b83d101c68fe741 diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java index e224ff74c2..d1a0cf420a 100644 --- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java +++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/AlarmQueryEsDAO.java @@ -90,6 +90,7 @@ public class AlarmQueryEsDAO extends EsDAO implements IAlarmQueryDAO { AlarmMessage message = new AlarmMessage(); message.setId(String.valueOf(alarmRecord.getId0())); + message.setId1(String.valueOf(alarmRecord.getId1())); message.setMessage(alarmRecord.getAlarmMessage()); message.setStartTime(alarmRecord.getStartTime()); message.setScope(Scope.Finder.valueOf(alarmRecord.getScope())); diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ESEventQueryDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ESEventQueryDAO.java index c8c9c0365c..749037b477 100644 --- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ESEventQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/ESEventQueryDAO.java @@ -18,6 +18,7 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query; +import java.io.IOException; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -53,26 +54,27 @@ public class ESEventQueryDAO extends EsDAO implements IEventQueryDAO { @Override public Events queryEvents(final EventQueryCondition condition) throws Exception { final SearchSourceBuilder sourceBuilder = buildQuery(condition); + return getEventsResultByCurrentBuilder(sourceBuilder); + } - final SearchResponse response = getClient() - .search(IndexController.LogicIndicesRegister.getPhysicalTableName(Event.INDEX_NAME), sourceBuilder); + @Override + public Events queryEvents(List conditionList) throws Exception { + final SearchSourceBuilder sourceBuilder = buildQuery(conditionList); + return getEventsResultByCurrentBuilder(sourceBuilder); + } + private Events getEventsResultByCurrentBuilder(final SearchSourceBuilder sourceBuilder) throws IOException { + final SearchResponse response = getClient() + .search(IndexController.LogicIndicesRegister.getPhysicalTableName(Event.INDEX_NAME), sourceBuilder); final Events events = new Events(); events.setTotal((int) response.getHits().totalHits); events.setEvents(Stream.of(response.getHits().getHits()) - .map(this::parseSearchHit) - .collect(Collectors.toList())); - + .map(this::parseSearchHit) + .collect(Collectors.toList())); return events; } - protected SearchSourceBuilder buildQuery(final EventQueryCondition condition) { - final SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource(); - final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); - sourceBuilder.query(boolQueryBuilder); - - final List mustQueryList = boolQueryBuilder.must(); - + private void buildMustQueryListByCondition(final EventQueryCondition condition, final List mustQueryList) { if (!isNullOrEmpty(condition.getUuid())) { mustQueryList.add(QueryBuilders.termQuery(Event.UUID, condition.getUuid())); } @@ -87,8 +89,8 @@ public class ESEventQueryDAO extends EsDAO implements IEventQueryDAO { } if (!isNullOrEmpty(source.getEndpoint())) { mustQueryList.add(QueryBuilders.matchPhraseQuery( - MatchCNameBuilder.INSTANCE.build(Event.ENDPOINT), - source.getEndpoint() + MatchCNameBuilder.INSTANCE.build(Event.ENDPOINT), + source.getEndpoint() )); } } @@ -105,13 +107,40 @@ public class ESEventQueryDAO extends EsDAO implements IEventQueryDAO { if (startTime != null) { if (startTime.getStartTimestamp() > 0) { mustQueryList.add(QueryBuilders.rangeQuery(Event.START_TIME) - .gt(startTime.getStartTimestamp())); + .gt(startTime.getStartTimestamp())); } if (startTime.getEndTimestamp() > 0) { mustQueryList.add(QueryBuilders.rangeQuery(Event.END_TIME) - .lt(startTime.getEndTimestamp())); + .lt(startTime.getEndTimestamp())); } } + } + + protected SearchSourceBuilder buildQuery(final List conditionList) { + final SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource(); + BoolQueryBuilder linkShouldBuilder = QueryBuilders.boolQuery(); + sourceBuilder.query(linkShouldBuilder); + conditionList.forEach(condition -> { + final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + final List mustQueryList = boolQueryBuilder.must(); + linkShouldBuilder.should(boolQueryBuilder); + buildMustQueryListByCondition(condition, mustQueryList); + }); + EventQueryCondition condition = conditionList.get(0); + final Order queryOrder = isNull(condition.getOrder()) ? Order.DES : condition.getOrder(); + sourceBuilder.sort(Event.START_TIME, Order.DES.equals(queryOrder) ? SortOrder.DESC : SortOrder.ASC); + sourceBuilder.size(condition.getSize()); + return sourceBuilder; + } + + protected SearchSourceBuilder buildQuery(final EventQueryCondition condition) { + final SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource(); + final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + sourceBuilder.query(boolQueryBuilder); + + final List mustQueryList = boolQueryBuilder.must(); + + buildMustQueryListByCondition(condition, mustQueryList); final Order queryOrder = isNull(condition.getOrder()) ? Order.DES : condition.getOrder(); sourceBuilder.sort(Event.START_TIME, Order.DES.equals(queryOrder) ? SortOrder.DESC : SortOrder.ASC); diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java index 91dd56b1cd..7efa998502 100644 --- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java +++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/AlarmQueryEs7DAO.java @@ -92,6 +92,7 @@ public class AlarmQueryEs7DAO extends EsDAO implements IAlarmQueryDAO { AlarmMessage message = new AlarmMessage(); message.setId(String.valueOf(alarmRecord.getId0())); + message.setId1(String.valueOf(alarmRecord.getId1())); message.setMessage(alarmRecord.getAlarmMessage()); message.setStartTime(alarmRecord.getStartTime()); message.setScope(Scope.Finder.valueOf(alarmRecord.getScope())); diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/ES7EventQueryDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/ES7EventQueryDAO.java index 2198791cc3..2ddfd7aaeb 100644 --- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/ES7EventQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/ES7EventQueryDAO.java @@ -18,6 +18,8 @@ package org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query; +import java.io.IOException; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.skywalking.oap.server.core.event.Event; @@ -37,16 +39,24 @@ public class ES7EventQueryDAO extends ESEventQueryDAO { @Override public Events queryEvents(final EventQueryCondition condition) throws Exception { final SearchSourceBuilder sourceBuilder = buildQuery(condition); + return getEventsResultByCurrentBuilder(sourceBuilder); + } + @Override + public Events queryEvents(List conditionList) throws Exception { + final SearchSourceBuilder sourceBuilder = buildQuery(conditionList); + return getEventsResultByCurrentBuilder(sourceBuilder); + } + + private Events getEventsResultByCurrentBuilder(final SearchSourceBuilder sourceBuilder) throws IOException { final SearchResponse response = getClient() - .search(IndexController.LogicIndicesRegister.getPhysicalTableName(Event.INDEX_NAME), sourceBuilder); + .search(IndexController.LogicIndicesRegister.getPhysicalTableName(Event.INDEX_NAME), sourceBuilder); final Events events = new Events(); events.setTotal(response.getHits().getTotalHits().value); events.setEvents(Stream.of(response.getHits().getHits()) - .map(this::parseSearchHit) - .collect(Collectors.toList())); - + .map(this::parseSearchHit) + .collect(Collectors.toList())); return events; } } diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/EventQueryDAO.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/EventQueryDAO.java index 767ebcf743..ab36ca28e6 100644 --- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/EventQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/EventQueryDAO.java @@ -19,9 +19,11 @@ package org.apache.skywalking.oap.server.storage.plugin.influxdb.query; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.oap.server.core.event.Event; @@ -38,6 +40,7 @@ import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants; import org.influxdb.dto.Query; import org.influxdb.dto.QueryResult; import org.influxdb.querybuilder.SelectQueryImpl; +import org.influxdb.querybuilder.WhereNested; import org.influxdb.querybuilder.WhereQueryImpl; import static com.google.common.base.Strings.isNullOrEmpty; @@ -55,35 +58,24 @@ public class EventQueryDAO implements IEventQueryDAO { @Override public Events queryEvents(final EventQueryCondition condition) throws Exception { - final WhereQueryImpl recallQuery = buildQuery(condition); + List> whereQueries = buildWhereQueries(condition); - final SelectQueryImpl countQuery = select().count(Event.UUID).from(client.getDatabase(), Event.INDEX_NAME); - recallQuery.getClauses().forEach(countQuery::where); + buildQueryByCondition(whereQueries, condition); - final Query query = new Query(countQuery.getCommand() + recallQuery.getCommand()); - final List results = client.query(query); - if (log.isDebugEnabled()) { - log.debug("SQL: {}", query.getCommand()); - log.debug("Result: {}", results); - } - if (results.size() != 2) { - throw new IOException("Expecting to get 2 Results, but it is " + results.size()); - } + List results = execute(whereQueries.get(0), whereQueries.get(1)); - final QueryResult.Series counterSeries = results.get(0).getSeries().get(0); - final List recallSeries = results.get(1).getSeries(); + return buildEventsByQueryResult(results); + } - final Events events = new Events(); + @Override + public Events queryEvents(List conditionList) throws Exception { + List> whereQueries = buildWhereQueries(conditionList.get(0)); - events.setTotal(((Number) counterSeries.getValues().get(0).get(1)).longValue()); + buildQueryByCondition(whereQueries, conditionList); - recallSeries.forEach( - series -> series.getValues().forEach( - values -> events.getEvents().add(parseSeriesValues(series, values)) - ) - ); + List results = execute(whereQueries.get(0), whereQueries.get(1)); - return events; + return buildEventsByQueryResult(results); } protected org.apache.skywalking.oap.server.core.query.type.event.Event parseSeriesValues(final QueryResult.Series series, final List values) { @@ -116,49 +108,147 @@ public class EventQueryDAO implements IEventQueryDAO { return event; } - protected WhereQueryImpl buildQuery(final EventQueryCondition condition) { + protected List> buildWhereQueries(final EventQueryCondition condition) { + List> queries = new ArrayList<>(2); final String topFunc = Order.DES.equals(condition.getOrder()) ? InfluxConstants.SORT_DES : InfluxConstants.SORT_ASC; - final WhereQueryImpl query = - select().raw(ALL_FIELDS) - .function(topFunc, Event.START_TIME, condition.getSize()) - .from(client.getDatabase(), Event.INDEX_NAME) - .where(); + final WhereQueryImpl recallWhereQuery = + select().raw(ALL_FIELDS) + .function(topFunc, Event.START_TIME, condition.getSize()) + .from(client.getDatabase(), Event.INDEX_NAME) + .where(); + final SelectQueryImpl countQuery = select().count(Event.UUID).from(client.getDatabase(), Event.INDEX_NAME); + final WhereQueryImpl countWhereQuery = countQuery.where(); + queries.add(countWhereQuery); + queries.add(recallWhereQuery); + return queries; + } + protected void buildQueryByCondition(List> queries, EventQueryCondition condition) { + WhereQueryImpl countWhereQuery = queries.get(0); + WhereQueryImpl recallWhereQuery = queries.get(1); if (!isNullOrEmpty(condition.getUuid())) { - query.and(eq(Event.UUID, condition.getUuid())); + recallWhereQuery.and(eq(Event.UUID, condition.getUuid())); + countWhereQuery.and(eq(Event.UUID, condition.getUuid())); } final Source source = condition.getSource(); if (source != null) { if (!isNullOrEmpty(source.getService())) { - query.and(eq(Event.SERVICE, source.getService())); + recallWhereQuery.and(eq(Event.SERVICE, source.getService())); + countWhereQuery.and(eq(Event.SERVICE, source.getService())); } if (!isNullOrEmpty(source.getServiceInstance())) { - query.and(eq(Event.SERVICE_INSTANCE, source.getServiceInstance())); + recallWhereQuery.and(eq(Event.SERVICE_INSTANCE, source.getServiceInstance())); + countWhereQuery.and(eq(Event.SERVICE_INSTANCE, source.getServiceInstance())); } if (!isNullOrEmpty(source.getEndpoint())) { - query.and(contains(Event.ENDPOINT, source.getEndpoint().replaceAll("/", "\\\\/"))); + recallWhereQuery.and(contains(Event.ENDPOINT, source.getEndpoint().replaceAll("/", "\\\\/"))); + countWhereQuery.and(contains(Event.ENDPOINT, source.getEndpoint().replaceAll("/", "\\\\/"))); } } if (!isNullOrEmpty(condition.getName())) { - query.and(eq(InfluxConstants.NAME, condition.getName())); + recallWhereQuery.and(eq(InfluxConstants.NAME, condition.getName())); + countWhereQuery.and(eq(InfluxConstants.NAME, condition.getName())); } if (condition.getType() != null) { - query.and(eq(Event.TYPE, condition.getType().name())); + recallWhereQuery.and(eq(Event.TYPE, condition.getType().name())); + countWhereQuery.and(eq(Event.TYPE, condition.getType().name())); } final Duration startTime = condition.getTime(); if (startTime != null) { if (startTime.getStartTimestamp() > 0) { - query.and(gt(Event.START_TIME, startTime.getStartTimestamp())); + recallWhereQuery.and(gt(Event.START_TIME, startTime.getStartTimestamp())); + countWhereQuery.and(gt(Event.START_TIME, startTime.getStartTimestamp())); } if (startTime.getEndTimestamp() > 0) { - query.and(lt(Event.END_TIME, startTime.getEndTimestamp())); + recallWhereQuery.and(lt(Event.END_TIME, startTime.getEndTimestamp())); + countWhereQuery.and(lt(Event.END_TIME, startTime.getEndTimestamp())); + } + } + } + + protected void buildQueryByCondition(List> queries, List conditions) { + WhereQueryImpl countWhereQuery = queries.get(0); + WhereQueryImpl recallWhereQuery = queries.get(1); + conditions.stream().forEach(c -> { + WhereNested> recallOrNested = recallWhereQuery.orNested(); + WhereNested> countOrNested = countWhereQuery.orNested(); + // by current condition, we should not have uuid. If one day you need to use UUIDs as the query condition, this might be applied. + if (!isNullOrEmpty(c.getUuid())) { + recallWhereQuery.and(eq(Event.UUID, c.getUuid())); + countWhereQuery.and(eq(Event.UUID, c.getUuid())); + } + + final Source source = c.getSource(); + if (source != null) { + if (!isNullOrEmpty(source.getService())) { + recallOrNested.and(eq(Event.SERVICE, source.getService())); + countOrNested.and(eq(Event.SERVICE, source.getService())); + } + if (!isNullOrEmpty(source.getServiceInstance())) { + recallOrNested.and(eq(Event.SERVICE_INSTANCE, source.getServiceInstance())); + countOrNested.and(eq(Event.SERVICE_INSTANCE, source.getServiceInstance())); + } + if (!isNullOrEmpty(source.getEndpoint())) { + recallOrNested.and(contains(Event.ENDPOINT, source.getEndpoint().replaceAll("/", "\\\\/"))); + countOrNested.and(contains(Event.ENDPOINT, source.getEndpoint().replaceAll("/", "\\\\/"))); + } + } + + if (!isNullOrEmpty(c.getName())) { + recallOrNested.and(eq(InfluxConstants.NAME, c.getName())); + countOrNested.and(eq(InfluxConstants.NAME, c.getName())); + } + + if (c.getType() != null) { + recallOrNested.and(eq(Event.TYPE, c.getType().name())); + countOrNested.and(eq(Event.TYPE, c.getType().name())); + } + + final Duration startTime = c.getTime(); + if (startTime != null) { + if (startTime.getStartTimestamp() > 0) { + recallOrNested.and(gt(Event.START_TIME, startTime.getStartTimestamp())); + countOrNested.and(gt(Event.START_TIME, startTime.getStartTimestamp())); + } + if (startTime.getEndTimestamp() > 0) { + recallOrNested.and(lt(Event.END_TIME, startTime.getEndTimestamp())); + countOrNested.and(lt(Event.END_TIME, startTime.getEndTimestamp())); + } } + recallOrNested.close(); + countOrNested.close(); + }); + } + + protected List execute(WhereQueryImpl countWhereQuery, WhereQueryImpl recallWhereQuery) throws IOException { + final Query query = new Query(countWhereQuery.getCommand() + recallWhereQuery.getCommand()); + final List results = client.query(query); + if (log.isDebugEnabled()) { + log.debug("SQL: {}", query.getCommand()); + log.debug("Result: {}", results); } + if (results.size() != 2) { + throw new IOException("Expecting to get 2 Results, but it is " + results.size()); + } + return results; + } + + protected Events buildEventsByQueryResult(List results) { + final QueryResult.Series counterSeries = results.get(0).getSeries().get(0); + final List recallSeries = results.get(1).getSeries(); - return query; + final Events events = new Events(); + events.setTotal(((Number) counterSeries.getValues().get(0).get(1)).longValue()); + + recallSeries.forEach( + series -> series.getValues().forEach( + values -> events.getEvents().add(parseSeriesValues(series, values)) + ) + ); + return events; } } diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java index 472b4fea3b..f246a18517 100644 --- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2AlarmQueryDAO.java @@ -128,6 +128,7 @@ public class H2AlarmQueryDAO implements IAlarmQueryDAO { while (resultSet.next()) { AlarmMessage message = new AlarmMessage(); message.setId(resultSet.getString(AlarmRecord.ID0)); + message.setId1(resultSet.getString(AlarmRecord.ID1)); message.setMessage(resultSet.getString(AlarmRecord.ALARM_MESSAGE)); message.setStartTime(resultSet.getLong(AlarmRecord.START_TIME)); message.setScope(Scope.Finder.valueOf(resultSet.getInt(AlarmRecord.SCOPE))); diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2EventQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2EventQueryDAO.java index 865b2e6f7f..43d8f95111 100644 --- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2EventQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2EventQueryDAO.java @@ -18,20 +18,22 @@ package org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao; +import io.vavr.Tuple; +import io.vavr.Tuple2; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.oap.server.core.event.Event; import org.apache.skywalking.oap.server.core.query.input.Duration; import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition; +import org.apache.skywalking.oap.server.core.query.type.event.EventType; import org.apache.skywalking.oap.server.core.query.type.event.Events; import org.apache.skywalking.oap.server.core.query.type.event.Source; -import org.apache.skywalking.oap.server.core.query.type.event.EventType; import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO; import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient; @@ -44,79 +46,76 @@ public class H2EventQueryDAO implements IEventQueryDAO { @Override public Events queryEvents(final EventQueryCondition condition) throws Exception { - final List conditions = new ArrayList<>(); - final List parameters = new ArrayList<>(); + final Tuple2, Stream> conditionsParametersPair = buildQuery(condition); + final Stream conditions = conditionsParametersPair._1(); + final Object[] parameters = conditionsParametersPair._2().toArray(); + final String whereClause = conditions.collect(Collectors.joining(" and ", " where ", "")); - if (!isNullOrEmpty(condition.getUuid())) { - conditions.add(Event.UUID + "=?"); - parameters.add(condition.getUuid()); - } + final Events result = new Events(); - final Source source = condition.getSource(); - if (source != null) { - if (!isNullOrEmpty(source.getService())) { - conditions.add(Event.SERVICE + "=?"); - parameters.add(source.getService()); - } - if (!isNullOrEmpty(source.getServiceInstance())) { - conditions.add(Event.SERVICE_INSTANCE + "=?"); - parameters.add(source.getServiceInstance()); + try (final Connection connection = client.getConnection()) { + String sql = "select count(1) total from " + Event.INDEX_NAME + whereClause; + if (log.isDebugEnabled()) { + log.debug("Count SQL: {}, parameters: {}", sql, parameters); } - if (!isNullOrEmpty(source.getEndpoint())) { - conditions.add(Event.ENDPOINT + "=?"); - parameters.add(source.getEndpoint()); + try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters)) { + if (!resultSet.next()) { + return result; + } + result.setTotal(resultSet.getInt("total")); } - } - if (!isNullOrEmpty(condition.getName())) { - conditions.add(Event.NAME + "=?"); - parameters.add(condition.getName()); - } - - if (condition.getType() != null) { - conditions.add(Event.TYPE + "=?"); - parameters.add(condition.getType().name()); - } - - final Duration time = condition.getTime(); - if (time != null) { - if (time.getStartTimestamp() > 0) { - conditions.add(Event.START_TIME + ">?"); - parameters.add(time.getStartTimestamp()); + sql = "select * from " + Event.INDEX_NAME + whereClause + " limit " + condition.getSize(); + if (log.isDebugEnabled()) { + log.debug("Query SQL: {}, parameters: {}", sql, parameters); } - if (time.getEndTimestamp() > 0) { - conditions.add(Event.END_TIME + " conditions) throws Exception { + final List, Stream>> conditionsParametersPair = conditions.stream() + .map(this::buildQuery) + .collect(Collectors.toList()); + final Object[] parameters = conditionsParametersPair.stream() + .map(Tuple2::_2) + .reduce(Stream.empty(), Stream::concat) + .toArray(); + final String whereClause = conditionsParametersPair.stream() + .map(Tuple2::_1) + .map(it -> it.collect(Collectors.joining(" and "))) + .collect(Collectors.joining(" or ", " where ", "")); + final int size = conditions.stream().mapToInt(EventQueryCondition::getSize).sum(); final Events result = new Events(); - try (final Connection connection = client.getConnection()) { String sql = "select count(1) total from " + Event.INDEX_NAME + whereClause; if (log.isDebugEnabled()) { log.debug("Count SQL: {}, parameters: {}", sql, parameters); } - try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters.toArray())) { + try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters)) { if (!resultSet.next()) { return result; } result.setTotal(resultSet.getInt("total")); } - - sql = "select * from " + Event.INDEX_NAME + whereClause + " limit " + condition.getSize(); + sql = "select * from " + Event.INDEX_NAME + whereClause + " limit " + size; if (log.isDebugEnabled()) { log.debug("Query SQL: {}, parameters: {}", sql, parameters); } - try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters.toArray())) { + try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters)) { while (resultSet.next()) { result.getEvents().add(parseResultSet(resultSet)); } } } - return result; } @@ -139,4 +138,54 @@ public class H2EventQueryDAO implements IEventQueryDAO { return event; } + + protected Tuple2, Stream> buildQuery(final EventQueryCondition condition) { + final Stream.Builder conditions = Stream.builder(); + final Stream.Builder parameters = Stream.builder(); + + if (!isNullOrEmpty(condition.getUuid())) { + conditions.add(Event.UUID + "=?"); + parameters.add(condition.getUuid()); + } + + final Source source = condition.getSource(); + if (source != null) { + if (!isNullOrEmpty(source.getService())) { + conditions.add(Event.SERVICE + "=?"); + parameters.add(source.getService()); + } + if (!isNullOrEmpty(source.getServiceInstance())) { + conditions.add(Event.SERVICE_INSTANCE + "=?"); + parameters.add(source.getServiceInstance()); + } + if (!isNullOrEmpty(source.getEndpoint())) { + conditions.add(Event.ENDPOINT + "=?"); + parameters.add(source.getEndpoint()); + } + } + + if (!isNullOrEmpty(condition.getName())) { + conditions.add(Event.NAME + "=?"); + parameters.add(condition.getName()); + } + + if (condition.getType() != null) { + conditions.add(Event.TYPE + "=?"); + parameters.add(condition.getType().name()); + } + + final Duration time = condition.getTime(); + if (time != null) { + if (time.getStartTimestamp() > 0) { + conditions.add(Event.START_TIME + ">?"); + parameters.add(time.getStartTimestamp()); + } + if (time.getEndTimestamp() > 0) { + conditions.add(Event.END_TIME + "> { private String start; private String end; private String step = "SECOND"; + private String name; public String start() { if (start != null) { @@ -135,4 +138,16 @@ public abstract class AbstractQuery> { this.step = "SECOND"; return (T) this; } + + public String name() { + if (!StringUtils.isEmpty(name)) { + return name; + } + return null; + } + + public T name(String name) { + this.name = name; + return (T) this; + } } diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/Alarm.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/Alarm.java index 6a2a2fec49..95a29da009 100644 --- a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/Alarm.java +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/Alarm.java @@ -20,6 +20,7 @@ package org.apache.skywalking.e2e.alarm; import lombok.Data; import lombok.experimental.Accessors; import org.apache.skywalking.e2e.common.KeyValue; +import org.apache.skywalking.e2e.event.Event; import java.util.List; @@ -31,4 +32,5 @@ public class Alarm { private String id; private String message; private List tags; + private List events; } diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmMatcher.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmMatcher.java index f047b2b26c..28753e14bb 100644 --- a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmMatcher.java +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmMatcher.java @@ -18,15 +18,20 @@ package org.apache.skywalking.e2e.alarm; import lombok.Data; +import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.e2e.common.KeyValue; import org.apache.skywalking.e2e.common.KeyValueMatcher; +import org.apache.skywalking.e2e.event.Event; +import org.apache.skywalking.e2e.event.EventMatcher; import org.apache.skywalking.e2e.verification.AbstractMatcher; +import org.springframework.util.CollectionUtils; import java.util.List; import static java.util.Objects.nonNull; import static org.assertj.core.api.Assertions.fail; +@Slf4j @Data public class AlarmMatcher extends AbstractMatcher { private String startTime; @@ -34,10 +39,10 @@ public class AlarmMatcher extends AbstractMatcher { private String id; private String message; private List tags; + private List events; @Override public void verify(Alarm alarm) { - doVerify(this.startTime, alarm.getStartTime()); doVerify(this.scope, alarm.getScope()); doVerify(this.id, alarm.getId()); doVerify(this.message, alarm.getMessage()); @@ -57,5 +62,22 @@ public class AlarmMatcher extends AbstractMatcher { } } } + + if (!CollectionUtils.isEmpty(getEvents())) { + for (final EventMatcher matcher : getEvents()) { + boolean matched = false; + for (final Event event : alarm.getEvents()) { + try { + matcher.verify(event); + matched = true; + } catch (Throwable ignore) { + //ignore. + } + } + if (!matched) { + fail("\nExpected: %s\n Actual: %s", getEvents(), alarm.getEvents()); + } + } + } } } diff --git a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmQuery.java b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmQuery.java index bc9af0091f..6011cd7689 100644 --- a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmQuery.java +++ b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/alarm/AlarmQuery.java @@ -18,6 +18,7 @@ package org.apache.skywalking.e2e.alarm; import org.apache.skywalking.e2e.AbstractQuery; +import org.apache.skywalking.e2e.event.Event; import java.util.ArrayList; import java.util.Collections; @@ -28,15 +29,26 @@ import java.util.HashMap; public class AlarmQuery extends AbstractQuery { private List> tags = Collections.emptyList(); + private List events = Collections.emptyList(); + public List> tags() { return tags; } + public List events() { + return events; + } + public AlarmQuery tags(List> tags) { this.tags = tags; return this; } + public AlarmQuery events(List events) { + this.events = events; + return this; + } + public AlarmQuery addTag(String key, String value) { if (Collections.EMPTY_LIST.equals(tags)) { tags = new ArrayList<>(); @@ -47,4 +59,13 @@ public class AlarmQuery extends AbstractQuery { tags.add(tag); return this; } + + public AlarmQuery addEvents(List events) { + if (Collections.EMPTY_LIST.equals(events)) { + events = new ArrayList<>(); + } + + events.addAll(events); + return this; + } } diff --git a/test/e2e/e2e-data/src/main/resources/read-alarms.gql b/test/e2e/e2e-data/src/main/resources/read-alarms.gql index fc9787c849..8fd912ad5a 100644 --- a/test/e2e/e2e-data/src/main/resources/read-alarms.gql +++ b/test/e2e/e2e-data/src/main/resources/read-alarms.gql @@ -29,6 +29,19 @@ tags { key, value } + events { + name + source { + service serviceInstance endpoint + } + startTime + endTime + message + parameters { + key value + } + uuid + } } }}", "variables":{ diff --git a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/alarm/AlarmE2E.java b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/alarm/AlarmE2E.java index facde91e3e..ea8c887030 100644 --- a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/alarm/AlarmE2E.java +++ b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/alarm/AlarmE2E.java @@ -17,6 +17,8 @@ package org.apache.skywalking.e2e.alarm; +import java.util.List; +import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.e2e.annotation.ContainerHostAndPort; import org.apache.skywalking.e2e.annotation.DockerCompose; @@ -35,9 +37,6 @@ import org.junit.jupiter.api.TestMethodOrder; import org.springframework.http.ResponseEntity; import org.testcontainers.containers.DockerComposeContainer; -import java.util.List; -import java.util.concurrent.TimeUnit; - import static org.apache.skywalking.e2e.utils.Times.now; import static org.apache.skywalking.e2e.utils.Yamls.load; diff --git a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-critical.yml b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-critical.yml index af0012b246..4bc326d106 100644 --- a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-critical.yml +++ b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-critical.yml @@ -24,6 +24,9 @@ matchers: value: CRITICAL - key: receivers value: zhangsan + events: + - source: + service: e2e-service-provider - startTime: gt 0 scope: Service id: ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1 @@ -33,4 +36,6 @@ matchers: value: CRITICAL - key: receivers value: zhangsan - + events: + - source: + service: e2e-service-provider diff --git a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-warn.yml b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-warn.yml index 3809e66206..43fc398a25 100644 --- a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-warn.yml +++ b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-after-graphql-warn.yml @@ -24,6 +24,9 @@ matchers: value: WARNING - key: receivers value: lisi + events: + - source: + service: e2e-service-provider - startTime: gt 0 scope: Service id: ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1 @@ -33,3 +36,6 @@ matchers: value: WARNING - key: receivers value: lisi + events: + - source: + service: e2e-service-provider diff --git a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-critical.yml b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-critical.yml index 4ae75a21ee..6c0ab9d4ce 100644 --- a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-critical.yml +++ b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-critical.yml @@ -24,3 +24,6 @@ matchers: value: CRITICAL - key: receivers value: zhangsan + events: + - source: + service: e2e-service-provider \ No newline at end of file diff --git a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-warn.yml b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-warn.yml index d95de2fd58..be8de040af 100644 --- a/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-warn.yml +++ b/test/e2e/e2e-test/src/test/resources/expected/alarm/silence-before-graphql-warn.yml @@ -24,3 +24,6 @@ matchers: value: WARNING - key: receivers value: lisi + events: + - source: + service: e2e-service-provider \ No newline at end of file -- GitLab