From b9041d6b817c950b61ada6ce0137f67460258f7c Mon Sep 17 00:00:00 2001 From: emeroad Date: Mon, 19 Aug 2024 12:17:13 +0900 Subject: [PATCH] [#11346] Refactory AgentEventQuery --- .../collector/AgentEventDataCollector.java | 7 +- .../alarm/checker/DeadlockCheckerTest.java | 18 ++-- .../controller/AgentInfoController.java | 4 +- .../pinpoint/web/dao/AgentEventDao.java | 4 +- .../dao/hbase/AgentEventFilterBuilder.java | 73 +++++++++++++++ .../web/dao/hbase/HbaseAgentEventDao.java | 43 +++++---- .../web/service/AgentEventService.java | 10 +- .../web/service/AgentEventServiceImpl.java | 15 +-- .../web/service/AgentInfoServiceImpl.java | 6 +- .../component/ActiveAgentValidator.java | 2 +- .../service/component/AgentEventQuery.java | 69 ++++++++++++++ .../DefaultActiveAgentValidator.java | 16 ++-- .../dao/hbase/AgentEventQueryBuilderTest.java | 93 +++++++++++++++++++ .../DefaultActiveAgentValidatorTest.java | 6 +- 14 files changed, 310 insertions(+), 56 deletions(-) create mode 100644 web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventFilterBuilder.java create mode 100644 web/src/main/java/com/navercorp/pinpoint/web/service/component/AgentEventQuery.java create mode 100644 web/src/test/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventQueryBuilderTest.java diff --git a/batch/src/main/java/com/navercorp/pinpoint/batch/alarm/collector/AgentEventDataCollector.java b/batch/src/main/java/com/navercorp/pinpoint/batch/alarm/collector/AgentEventDataCollector.java index 49430f77595e1..2857648d59313 100644 --- a/batch/src/main/java/com/navercorp/pinpoint/batch/alarm/collector/AgentEventDataCollector.java +++ b/batch/src/main/java/com/navercorp/pinpoint/batch/alarm/collector/AgentEventDataCollector.java @@ -21,11 +21,12 @@ import com.navercorp.pinpoint.common.server.util.time.Range; import com.navercorp.pinpoint.web.alarm.DataCollectorCategory; import com.navercorp.pinpoint.web.dao.AgentEventDao; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -33,6 +34,8 @@ */ public class AgentEventDataCollector extends DataCollector { + private static final AgentEventQuery DEADLOCK = AgentEventQuery.include(Set.of(AgentEventType.AGENT_DEADLOCK_DETECTED)); + private final AgentEventDao agentEventDao; private final List agentIds; @@ -67,7 +70,7 @@ public void collect() { Range range = Range.between(timeSlotEndTime - slotInterval, timeSlotEndTime); for (String agentId : agentIds) { - List agentEventBoList = agentEventDao.getAgentEvents(agentId, range, Collections.emptySet()); + List agentEventBoList = agentEventDao.getAgentEvents(agentId, range, DEADLOCK); if (hasDeadlockEvent(agentEventBoList)) { agentDeadlockEventDetected.put(agentId, true); } diff --git a/batch/src/test/java/com/navercorp/pinpoint/batch/alarm/checker/DeadlockCheckerTest.java b/batch/src/test/java/com/navercorp/pinpoint/batch/alarm/checker/DeadlockCheckerTest.java index 435a6493255d4..496893064c3ef 100644 --- a/batch/src/test/java/com/navercorp/pinpoint/batch/alarm/checker/DeadlockCheckerTest.java +++ b/batch/src/test/java/com/navercorp/pinpoint/batch/alarm/checker/DeadlockCheckerTest.java @@ -25,6 +25,7 @@ import com.navercorp.pinpoint.web.alarm.DataCollectorCategory; import com.navercorp.pinpoint.web.alarm.vo.Rule; import com.navercorp.pinpoint.web.dao.AgentEventDao; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; import org.apache.commons.lang3.RandomUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -33,7 +34,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; -import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @@ -68,9 +68,9 @@ public void checkTest1() { Rule rule = new Rule(APPLICATION_NAME, SERVICE_TYPE, CheckerCategory.ERROR_COUNT.getName(), 50, "testGroup", false, false, false, ""); Range range = Range.between(START_TIME_MILLIS, CURRENT_TIME_MILLIS); - when(mockAgentEventDao.getAgentEvents(AGENT_ID_1, range, Set.of())).thenReturn(List.of(createAgentEvent(AGENT_ID_1, createEventTimestamp(), AgentEventType.AGENT_CLOSED_BY_SERVER))); - when(mockAgentEventDao.getAgentEvents(AGENT_ID_2, range, Set.of())).thenReturn(List.of(createAgentEvent(AGENT_ID_2, createEventTimestamp(), AgentEventType.AGENT_DEADLOCK_DETECTED))); - when(mockAgentEventDao.getAgentEvents(AGENT_ID_3, range, Set.of())).thenReturn(List.of(createAgentEvent(AGENT_ID_3, createEventTimestamp(), AgentEventType.AGENT_PING))); + when(mockAgentEventDao.getAgentEvents(AGENT_ID_1, range, allQuery())).thenReturn(List.of(createAgentEvent(AGENT_ID_1, createEventTimestamp(), AgentEventType.AGENT_CLOSED_BY_SERVER))); + when(mockAgentEventDao.getAgentEvents(AGENT_ID_2, range, allQuery())).thenReturn(List.of(createAgentEvent(AGENT_ID_2, createEventTimestamp(), AgentEventType.AGENT_DEADLOCK_DETECTED))); + when(mockAgentEventDao.getAgentEvents(AGENT_ID_3, range, allQuery())).thenReturn(List.of(createAgentEvent(AGENT_ID_3, createEventTimestamp(), AgentEventType.AGENT_PING))); AgentEventDataCollector dataCollector = new AgentEventDataCollector(DataCollectorCategory.AGENT_EVENT, mockAgentEventDao, mockAgentIds, CURRENT_TIME_MILLIS, INTERVAL_MILLIS); DeadlockChecker checker = new DeadlockChecker(dataCollector, rule); @@ -89,9 +89,9 @@ public void checkTest2() { Rule rule = new Rule(APPLICATION_NAME, SERVICE_TYPE, CheckerCategory.ERROR_COUNT.getName(), 50, "testGroup", false, false, false, ""); Range range = Range.between(START_TIME_MILLIS, CURRENT_TIME_MILLIS); - when(mockAgentEventDao.getAgentEvents(AGENT_ID_1, range, Set.of())).thenReturn(List.of(createAgentEvent(AGENT_ID_1, createEventTimestamp(), AgentEventType.AGENT_CLOSED_BY_SERVER))); - when(mockAgentEventDao.getAgentEvents(AGENT_ID_2, range, Set.of())).thenReturn(List.of(createAgentEvent(AGENT_ID_2, createEventTimestamp(), AgentEventType.AGENT_SHUTDOWN))); - when(mockAgentEventDao.getAgentEvents(AGENT_ID_3, range, Set.of())).thenReturn(List.of(createAgentEvent(AGENT_ID_3, createEventTimestamp(), AgentEventType.AGENT_PING))); + when(mockAgentEventDao.getAgentEvents(AGENT_ID_1, range, allQuery())).thenReturn(List.of(createAgentEvent(AGENT_ID_1, createEventTimestamp(), AgentEventType.AGENT_CLOSED_BY_SERVER))); + when(mockAgentEventDao.getAgentEvents(AGENT_ID_2, range, allQuery())).thenReturn(List.of(createAgentEvent(AGENT_ID_2, createEventTimestamp(), AgentEventType.AGENT_SHUTDOWN))); + when(mockAgentEventDao.getAgentEvents(AGENT_ID_3, range, allQuery())).thenReturn(List.of(createAgentEvent(AGENT_ID_3, createEventTimestamp(), AgentEventType.AGENT_PING))); AgentEventDataCollector dataCollector = new AgentEventDataCollector(DataCollectorCategory.AGENT_EVENT, mockAgentEventDao, mockAgentIds, CURRENT_TIME_MILLIS, INTERVAL_MILLIS); DeadlockChecker checker = new DeadlockChecker(dataCollector, rule); @@ -105,6 +105,10 @@ public void checkTest2() { assertThat(smsMessage).isEmpty(); } + private AgentEventQuery allQuery() { + return AgentEventQuery.all(); + } + private AgentEventBo createAgentEvent(String agentId, long eventTimestamp, AgentEventType agentEventType) { return new AgentEventBo(agentId, START_TIME_MILLIS, eventTimestamp, agentEventType); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentInfoController.java b/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentInfoController.java index 5a2bfe3288411..df855897f6418 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentInfoController.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentInfoController.java @@ -23,6 +23,7 @@ import com.navercorp.pinpoint.web.response.CodeResult; import com.navercorp.pinpoint.web.service.AgentEventService; import com.navercorp.pinpoint.web.service.AgentInfoService; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; import com.navercorp.pinpoint.web.view.tree.SimpleTreeView; import com.navercorp.pinpoint.web.view.tree.TreeNode; import com.navercorp.pinpoint.web.view.tree.TreeView; @@ -185,7 +186,8 @@ public List getAgentEvents( @RequestParam(value = "exclude", defaultValue = "") int[] excludeEventTypeCodes) { final Range range = Range.between(from, to); final Set excludeEventTypes = getAgentEventTypes(excludeEventTypeCodes); - return this.agentEventService.getAgentEvents(agentId, range, excludeEventTypes); + AgentEventQuery exclude = AgentEventQuery.exclude(excludeEventTypes); + return this.agentEventService.getAgentEvents(agentId, range, exclude); } private static Set getAgentEventTypes(int[] excludeEventTypeCodes) { diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java index b34c885b0edc8..a3aec08faea65 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentEventDao.java @@ -19,9 +19,9 @@ import com.navercorp.pinpoint.common.server.bo.event.AgentEventBo; import com.navercorp.pinpoint.common.server.util.AgentEventType; import com.navercorp.pinpoint.common.server.util.time.Range; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; import java.util.List; -import java.util.Set; /** * @author HyunGil Jeong @@ -30,6 +30,6 @@ public interface AgentEventDao { AgentEventBo getAgentEvent(String agentId, long eventTimestamp, AgentEventType eventType); - List getAgentEvents(String agentId, Range range, Set excludeEventTypes); + List getAgentEvents(String agentId, Range range, AgentEventQuery filter); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventFilterBuilder.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventFilterBuilder.java new file mode 100644 index 0000000000000..ce1668a936c6c --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventFilterBuilder.java @@ -0,0 +1,73 @@ +package com.navercorp.pinpoint.web.dao.hbase; + +import com.navercorp.pinpoint.common.server.util.AgentEventType; +import com.navercorp.pinpoint.common.util.CollectionUtils; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; +import org.apache.hadoop.hbase.CompareOperator; +import org.apache.hadoop.hbase.filter.BinaryComparator; +import org.apache.hadoop.hbase.filter.Filter; +import org.apache.hadoop.hbase.filter.FilterList; +import org.apache.hadoop.hbase.filter.QualifierFilter; +import org.apache.hadoop.hbase.util.Bytes; + +import java.util.Set; + +public class AgentEventFilterBuilder { + + public AgentEventFilterBuilder() { + + } + + public Filter queryToFilter(AgentEventQuery query) { + return switch (query.getQueryType()) { + case INCLUDE -> includeFilter(query.getEventTypes()); + case EXCLUDE -> excludeFilter(query.getEventTypes()); + case ALL -> null; + }; + } + + public Filter excludeFilter(Set excludeEventTypes) { + if (CollectionUtils.isEmpty(excludeEventTypes)) { + return null; + } + if (excludeEventTypes.size() == 1) { + AgentEventType event = excludeEventTypes.iterator().next(); + return excludeQualifierFilter(event); + } + + final FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); + for (AgentEventType excludeEventType : excludeEventTypes) { + Filter filter = excludeQualifierFilter(excludeEventType); + filterList.addFilter(filter); + } + return filterList; + } + + private Filter excludeQualifierFilter(AgentEventType excludeEventType) { + byte[] excludeQualifier = Bytes.toBytes(excludeEventType.getCode()); + return new QualifierFilter(CompareOperator.NOT_EQUAL, new BinaryComparator(excludeQualifier)); + } + + public Filter includeFilter(Set includeEventTypes) { + if (CollectionUtils.isEmpty(includeEventTypes)) { + return null; + } + if (includeEventTypes.size() == 1) { + AgentEventType event = includeEventTypes.iterator().next(); + return includeFilter(event); + } + + final FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE); + for (AgentEventType excludeEventType : includeEventTypes) { + Filter filter = includeFilter(excludeEventType); + filterList.addFilter(filter); + } + return filterList; + } + + private Filter includeFilter(AgentEventType excludeEventType) { + byte[] excludeQualifier = Bytes.toBytes(excludeEventType.getCode()); + return new QualifierFilter(CompareOperator.EQUAL, new BinaryComparator(excludeQualifier)); + } + +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java index 299050947f68e..868619603f795 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentEventDao.java @@ -29,13 +29,11 @@ import com.navercorp.pinpoint.common.server.util.time.Range; import com.navercorp.pinpoint.common.util.CollectionUtils; import com.navercorp.pinpoint.web.dao.AgentEventDao; -import org.apache.hadoop.hbase.CompareOperator; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.Scan; -import org.apache.hadoop.hbase.filter.BinaryComparator; -import org.apache.hadoop.hbase.filter.FilterList; -import org.apache.hadoop.hbase.filter.QualifierFilter; +import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.util.Bytes; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -44,7 +42,6 @@ import java.util.List; import java.util.Objects; -import java.util.Set; /** * @author HyunGil Jeong @@ -68,6 +65,8 @@ public class HbaseAgentEventDao implements AgentEventDao { private final AgentIdRowKeyEncoder rowKeyEncoder = new AgentIdRowKeyEncoder(); + private final AgentEventFilterBuilder filterBuilder = new AgentEventFilterBuilder(); + public HbaseAgentEventDao(HbaseOperations hbaseOperations, TableNameProvider tableNameProvider, @Qualifier("agentEventMapper") @@ -79,31 +78,37 @@ public HbaseAgentEventDao(HbaseOperations hbaseOperations, } @Override - public List getAgentEvents(String agentId, Range range, Set excludeEventTypes) { + public List getAgentEvents(String agentId, Range range, AgentEventQuery query) { Objects.requireNonNull(agentId, "agentId"); Objects.requireNonNull(range, "range"); + Objects.requireNonNull(query, "query"); + + Scan scan = createScan(agentId, range, query); + + + TableName table = tableNameProvider.getTableName(DESCRIPTOR.getTable()); + List agentEvents = this.hbaseOperations.find(table, scan, agentEventResultsExtractor); + logger.debug("getAgentEvents() query:{} agentEvents:{}", query, agentEvents); + return agentEvents; + } + + private Scan createScan(String agentId, Range range, AgentEventQuery query) { Scan scan = new Scan(); - scan.readVersions(1); scan.setCaching(SCANNER_CACHE_SIZE); scan.withStartRow(createRowKey(agentId, range.getTo())); scan.withStopRow(createRowKey(agentId, range.getFrom())); scan.addFamily(DESCRIPTOR.getName()); - if (CollectionUtils.hasLength(excludeEventTypes)) { - FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL); - for (AgentEventType excludeEventType : excludeEventTypes) { - byte[] excludeQualifier = Bytes.toBytes(excludeEventType.getCode()); - filterList.addFilter(new QualifierFilter(CompareOperator.NOT_EQUAL, new BinaryComparator(excludeQualifier))); - } - scan.setFilter(filterList); + Filter filter = filterBuilder.queryToFilter(query); + if (filter != null) { + scan.setFilter(filter); } - - TableName agentEventTableName = tableNameProvider.getTableName(DESCRIPTOR.getTable()); - List agentEvents = this.hbaseOperations.find(agentEventTableName, scan, agentEventResultsExtractor); - logger.debug("agentEvents found. {}", agentEvents); - return agentEvents; + if (query.isOneRowScan()) { + scan.setOneRowLimit(); + } + return scan; } @Override diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java index 0ecc7affecdcf..21993bc492511 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventService.java @@ -16,12 +16,12 @@ package com.navercorp.pinpoint.web.service; -import java.util.List; -import java.util.Set; - import com.navercorp.pinpoint.common.server.util.AgentEventType; -import com.navercorp.pinpoint.web.vo.AgentEvent; import com.navercorp.pinpoint.common.server.util.time.Range; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; +import com.navercorp.pinpoint.web.vo.AgentEvent; + +import java.util.List; /** * @author HyunGil Jeong @@ -32,6 +32,6 @@ public interface AgentEventService { List getAgentEvents(String agentId, Range range); - List getAgentEvents(String agentId, Range range, Set excludeEventTypeCodes); + List getAgentEvents(String agentId, Range range, AgentEventQuery query); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java index 8bad21191af3c..7ccc7cddb63f2 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentEventServiceImpl.java @@ -24,6 +24,7 @@ import com.navercorp.pinpoint.common.server.util.time.Range; import com.navercorp.pinpoint.common.util.ArrayUtils; import com.navercorp.pinpoint.web.dao.AgentEventDao; +import com.navercorp.pinpoint.web.service.component.AgentEventQuery; import com.navercorp.pinpoint.web.vo.AgentEvent; import com.navercorp.pinpoint.web.vo.DurationalAgentEvent; import org.apache.commons.collections4.CollectionUtils; @@ -37,7 +38,6 @@ import java.util.List; import java.util.Objects; import java.util.PriorityQueue; -import java.util.Set; /** * @author HyunGil Jeong @@ -54,7 +54,9 @@ public class AgentEventServiceImpl implements AgentEventService { private final AgentEventMessageDeserializerV1 agentEventMessageDeserializerV1; - public AgentEventServiceImpl(AgentEventDao agentEventDao, AgentEventMessageDeserializer agentEventMessageDeserializer, AgentEventMessageDeserializerV1 agentEventMessageDeserializerV1) { + public AgentEventServiceImpl(AgentEventDao agentEventDao, + AgentEventMessageDeserializer agentEventMessageDeserializer, + AgentEventMessageDeserializerV1 agentEventMessageDeserializerV1) { this.agentEventDao = Objects.requireNonNull(agentEventDao, "agentEventDao"); this.agentEventMessageDeserializer = Objects.requireNonNull(agentEventMessageDeserializer, "agentEventMessageDeserializer"); this.agentEventMessageDeserializerV1 = Objects.requireNonNull(agentEventMessageDeserializerV1, "agentEventMessageDeserializerV1"); @@ -62,15 +64,16 @@ public AgentEventServiceImpl(AgentEventDao agentEventDao, AgentEventMessageDeser @Override public List getAgentEvents(String agentId, Range range) { - return getAgentEvents(agentId, range, Collections.emptySet()); + return getAgentEvents(agentId, range, AgentEventQuery.all()); } @Override - public List getAgentEvents(String agentId, Range range, Set excludeEventTypeCodes) { + public List getAgentEvents(String agentId, Range range, AgentEventQuery query) { Objects.requireNonNull(agentId, "agentId"); - Objects.requireNonNull(excludeEventTypeCodes, "excludeEventTypeCodes"); + Objects.requireNonNull(query, "query"); + + List agentEventBos = this.agentEventDao.getAgentEvents(agentId, range, query); - List agentEventBos = this.agentEventDao.getAgentEvents(agentId, range, excludeEventTypeCodes); List agentEvents = createAgentEvents(agentEventBos); agentEvents.sort(AgentEvent.EVENT_TIMESTAMP_ASC_COMPARATOR); return agentEvents; diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java index 3365efddb52ca..03b919110b0f4 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java @@ -187,10 +187,10 @@ private boolean isActiveAgentPredicate(AgentAndStatus agentAndStatus, logger.trace("isActiveAgentPredicate {}", agentAndStatus); AgentInfo agentInfo = agentAndStatus.getAgentInfo(); if (agentInfoPredicate.test(agentInfo)) { - logger.trace("agentInfoPredicate=true"); + logger.trace("agentInfoPredicate=true {}", agentAndStatus); } if (agentStatusFilter.test(agentAndStatus.getStatus())) { - logger.trace("agentStatusFilter=true"); + logger.trace("agentStatusFilter=true {}", agentAndStatus); return true; } Application agent = new Application(agentInfo.getAgentId(), agentInfo.getServiceType()); @@ -198,7 +198,7 @@ private boolean isActiveAgentPredicate(AgentAndStatus agentAndStatus, if (activeAgentValidator.isActiveAgent(agent, agentVersion, range)) { return true; } - logger.trace("isActiveAgentPredicate=false"); + logger.trace("isActiveAgentPredicate=false {}", agentAndStatus); return false; } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/component/ActiveAgentValidator.java b/web/src/main/java/com/navercorp/pinpoint/web/service/component/ActiveAgentValidator.java index c1781118a892b..a24de7133521a 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/component/ActiveAgentValidator.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/component/ActiveAgentValidator.java @@ -14,5 +14,5 @@ public interface ActiveAgentValidator { boolean isActiveAgent(Application agent, String version, List ranges); - boolean isActiveAgentByPing(String agentId, Range range); + boolean isActiveAgentByEvent(String agentId, Range range); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/component/AgentEventQuery.java b/web/src/main/java/com/navercorp/pinpoint/web/service/component/AgentEventQuery.java new file mode 100644 index 0000000000000..ee192b963f9bf --- /dev/null +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/component/AgentEventQuery.java @@ -0,0 +1,69 @@ +package com.navercorp.pinpoint.web.service.component; + +import com.navercorp.pinpoint.common.server.util.AgentEventType; + +import java.util.Objects; +import java.util.Set; + +public class AgentEventQuery { + public enum QueryType { + INCLUDE, + EXCLUDE, + ALL + } + + public static final AgentEventQuery ALL = new AgentEventQuery(QueryType.ALL, Set.of()); + + private final QueryType queryType; + private final Set eventTypes; + private final boolean oneRowScan; + + public AgentEventQuery(QueryType queryType, Set eventTypes) { + this.queryType = Objects.requireNonNull(queryType, "queryType"); + this.eventTypes = Objects.requireNonNull(eventTypes, "eventTypes"); + this.oneRowScan = false; + } + + public AgentEventQuery(QueryType queryType, Set eventTypes, boolean oneRowScan) { + this.queryType = Objects.requireNonNull(queryType, "queryType"); + this.eventTypes = Objects.requireNonNull(eventTypes, "eventTypes"); + this.oneRowScan = oneRowScan; + } + + public QueryType getQueryType() { + return queryType; + } + + public boolean isOneRowScan() { + return oneRowScan; + } + + public AgentEventQuery withOneRowScan() { + return new AgentEventQuery(this.queryType, this.eventTypes, true); + } + + public Set getEventTypes() { + return eventTypes; + } + + public static AgentEventQuery include(Set includeEventTypes) { + return new AgentEventQuery(QueryType.INCLUDE, includeEventTypes); + } + + public static AgentEventQuery exclude(Set excludeEventTypes) { + return new AgentEventQuery(QueryType.EXCLUDE, excludeEventTypes); + } + + public static AgentEventQuery all() { + return ALL; + } + + @Override + public String toString() { + return "AgentEventQuery{" + + "queryType=" + queryType + + ", eventTypes=" + eventTypes + + ", oneRowScan=" + oneRowScan + + '}'; + } +} diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidator.java b/web/src/main/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidator.java index 23f6b21f41c3f..7d647d3738b70 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidator.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidator.java @@ -1,8 +1,9 @@ package com.navercorp.pinpoint.web.service.component; -import com.navercorp.pinpoint.common.server.util.AgentEventType; import com.navercorp.pinpoint.common.server.util.time.Range; +import com.navercorp.pinpoint.common.util.CollectionUtils; import com.navercorp.pinpoint.web.service.AgentEventService; +import com.navercorp.pinpoint.web.vo.AgentEvent; import com.navercorp.pinpoint.web.vo.Application; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,7 +27,7 @@ public DefaultActiveAgentValidator(AgentEventService agentEventService, LegacyAg @Override public boolean isActiveAgent(String agentId, Range range) { Objects.requireNonNull(agentId, "agentId"); - if (isActiveAgentByPing(agentId, range)) { + if (isActiveAgentByEvent(agentId, range)) { return true; } return agentCompatibility.isActiveAgent(agentId, range); @@ -43,7 +44,8 @@ public boolean isActiveAgent(Application agent, String version, Range range) { String agentId = agent.getName(); if (!agentCompatibility.isLegacyAgent(agent.getServiceTypeCode(), version)) { logger.trace("isActiveAgentByPing"); - if (isActiveAgentByPing(agentId, range)) { + + if (isActiveAgentByEvent(agentId, range)) { return true; } } else { @@ -66,10 +68,10 @@ public boolean isActiveAgent(Application agent, String version, List rang } @Override - public boolean isActiveAgentByPing(String agentId, Range range) { - return this.agentEventService.getAgentEvents(agentId, range) - .stream() - .anyMatch(e -> e.getEventTypeCode() == AgentEventType.AGENT_PING.getCode()); + public boolean isActiveAgentByEvent(String agentId, Range range) { + AgentEventQuery query = AgentEventQuery.all().withOneRowScan(); + List recentAgentEvent = this.agentEventService.getAgentEvents(agentId, range, query); + return CollectionUtils.hasLength(recentAgentEvent); } diff --git a/web/src/test/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventQueryBuilderTest.java b/web/src/test/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventQueryBuilderTest.java new file mode 100644 index 0000000000000..479b6913920c3 --- /dev/null +++ b/web/src/test/java/com/navercorp/pinpoint/web/dao/hbase/AgentEventQueryBuilderTest.java @@ -0,0 +1,93 @@ +package com.navercorp.pinpoint.web.dao.hbase; + +import com.navercorp.pinpoint.common.server.util.AgentEventType; +import io.jsonwebtoken.impl.lang.Bytes; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.filter.Filter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Set; + +class AgentEventQueryBuilderTest { + + AgentEventFilterBuilder filterBuilder = new AgentEventFilterBuilder(); + + @Test + void excludeFilter_single() throws IOException { + + Filter filter = filterBuilder.excludeFilter(Set.of(AgentEventType.AGENT_CONNECTED)); + + KeyValue connect = newKeyValue(AgentEventType.AGENT_CONNECTED); + + Filter.ReturnCode connectReturn = filter.filterCell(connect); + Assertions.assertEquals(Filter.ReturnCode.SKIP, connectReturn); + + + KeyValue ping = newKeyValue(AgentEventType.AGENT_PING); + + Filter.ReturnCode pingReturn = filter.filterCell(ping); + Assertions.assertEquals(Filter.ReturnCode.INCLUDE, pingReturn); + } + + @Test + void excludeFilter_multi() throws IOException { + + Filter filter = filterBuilder.excludeFilter(Set.of(AgentEventType.AGENT_CONNECTED, AgentEventType.AGENT_SHUTDOWN)); + + KeyValue connect = newKeyValue(AgentEventType.AGENT_CONNECTED); + + Filter.ReturnCode returnCode = filter.filterCell(connect); + Assertions.assertEquals(Filter.ReturnCode.SKIP, returnCode); + + + KeyValue ping = newKeyValue(AgentEventType.AGENT_PING); + + Filter.ReturnCode pingReturn = filter.filterCell(ping); + Assertions.assertEquals(Filter.ReturnCode.INCLUDE, pingReturn); + } + + private KeyValue newKeyValue(AgentEventType agentConnected) { + byte[] qualifier = Bytes.toBytes(agentConnected.getCode()); + return new KeyValue(new byte[1], new byte[1], qualifier); + } + + + @Test + void includeFilter_single() throws IOException { + + Filter filter = filterBuilder.includeFilter(Set.of(AgentEventType.AGENT_CONNECTED)); + + KeyValue connect = newKeyValue(AgentEventType.AGENT_CONNECTED); + + Filter.ReturnCode connectReturn = filter.filterCell(connect); + Assertions.assertEquals(Filter.ReturnCode.INCLUDE, connectReturn); + + + KeyValue ping = newKeyValue(AgentEventType.AGENT_PING); + + Filter.ReturnCode pingReturn = filter.filterCell(ping); + Assertions.assertEquals(Filter.ReturnCode.SKIP, pingReturn); + } + + + @Test + void includeFilter_multi() throws IOException { + + Filter filter = filterBuilder.includeFilter(Set.of(AgentEventType.AGENT_CONNECTED, AgentEventType.AGENT_SHUTDOWN)); + + KeyValue connect = newKeyValue(AgentEventType.AGENT_CONNECTED); + + Filter.ReturnCode connectReturn = filter.filterCell(connect); + Assertions.assertEquals(Filter.ReturnCode.INCLUDE, connectReturn); + + + KeyValue ping = newKeyValue(AgentEventType.AGENT_PING); + + Filter.ReturnCode pingReturn = filter.filterCell(ping); + Assertions.assertEquals(Filter.ReturnCode.SKIP, pingReturn); + } + + +} \ No newline at end of file diff --git a/web/src/test/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidatorTest.java b/web/src/test/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidatorTest.java index bad4afbca5a94..3918242632b20 100644 --- a/web/src/test/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidatorTest.java +++ b/web/src/test/java/com/navercorp/pinpoint/web/service/component/DefaultActiveAgentValidatorTest.java @@ -61,13 +61,13 @@ void isActiveAgent_new_node_without_ping() { Assertions.assertFalse(validator.isActiveAgent(node, "0.8.0", Range.between(0, 1))); - verify(agentEventService).getAgentEvents(any(), any()); + verify(agentEventService).getAgentEvents(any(), any(), any()); } @Test - void isActiveAgent_new_node_with_ping() { + void isActiveAgent_new_node_with_event() { AgentEvent ping = new AgentEvent("test", 1, 1, AgentEventType.AGENT_PING); - when(agentEventService.getAgentEvents(any(), any())).thenReturn(List.of(ping)); + when(agentEventService.getAgentEvents(any(), any(), any())).thenReturn(List.of(ping)); LegacyAgentCompatibility agentCompatibility = new DefaultLegacyAgentCompatibility(jvmGcDao); ActiveAgentValidator validator = new DefaultActiveAgentValidator(agentEventService, agentCompatibility);