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 13d89f6fb62e..c9c9098c622b 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 @@ -38,6 +38,7 @@ import com.navercorp.pinpoint.web.vo.timeline.inspector.InspectorTimeline; import com.navercorp.pinpoint.web.view.tree.SimpleTreeView; import com.navercorp.pinpoint.web.view.tree.TreeView; +import com.navercorp.pinpoint.web.vo.tree.SortByAgentInfo; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -59,6 +60,8 @@ public class AgentInfoController { private final AgentEventService agentEventService; + private SortByAgentInfo.Rules DEFAULT_SORTBY = SortByAgentInfo.Rules.AGENT_ID_ASC; + public AgentInfoController(AgentInfoService agentInfoService, AgentEventService agentEventService) { this.agentInfoService = Objects.requireNonNull(agentInfoService, "agentInfoService"); this.agentEventService = Objects.requireNonNull(agentEventService, "agentEventService"); @@ -76,7 +79,7 @@ public TreeView> getAgentList( @RequestParam("to") long to) { AgentStatusFilter filter = new DefaultAgentStatusFilter(from); long timestamp = to; - AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsList(filter, Range.between(from, to)); + AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsList(filter, Range.between(from, to)); return treeView(allAgentsList); } @@ -88,7 +91,7 @@ public TreeView> getAgentList( return treeView(allAgentsList); } - private static TreeView> treeView(AgentsMapByApplication agentsListsList) { + private static TreeView> treeView(AgentsMapByApplication agentsListsList) { List> list = agentsListsList.getAgentsListsList(); return new SimpleTreeView<>(list, InstancesList::getGroupName, InstancesList::getInstancesList); } @@ -108,7 +111,12 @@ public TreeView> getAgentList( new DefaultAgentStatusFilter(from) ); long timestamp = to; - AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(currentRunFilter, applicationName, Range.between(from, to)); + AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName( + currentRunFilter, + applicationName, + Range.between(from, to), + DEFAULT_SORTBY + ); return treeView(list); } @@ -119,7 +127,11 @@ public TreeView> getAgentList( AgentStatusFilter runningAgentFilter = new AgentStatusFilterChain( AgentStatusFilter::filterRunning ); - AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(runningAgentFilter, applicationName, Range.between(timestamp, timestamp)); + AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(runningAgentFilter, + applicationName, + Range.between(timestamp, timestamp), + DEFAULT_SORTBY + ); return treeView(list); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentListController.java b/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentListController.java index 77b416116a5b..d4ac8329ed51 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentListController.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentListController.java @@ -9,6 +9,7 @@ import com.navercorp.pinpoint.web.vo.agent.AgentStatusFilterChain; import com.navercorp.pinpoint.web.vo.agent.AgentStatusAndLink; import com.navercorp.pinpoint.web.vo.agent.DefaultAgentStatusFilter; +import com.navercorp.pinpoint.web.vo.agent.DetailedAgentInfo; import com.navercorp.pinpoint.web.vo.tree.InstancesList; import com.navercorp.pinpoint.web.vo.tree.AgentsMapByApplication; import com.navercorp.pinpoint.web.vo.tree.AgentsMapByHost; @@ -51,19 +52,18 @@ public TreeView> getAllAgentsList( @RequestParam("from") long from, @RequestParam("to") long to) { AgentStatusFilter filter = new DefaultAgentStatusFilter(from); - AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsList( + AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsList( filter, Range.between(from, to) ); return treeView(allAgentsList); } - private static TreeView> treeView(AgentsMapByApplication agentsListsList) { - List> list = agentsListsList.getAgentsListsList(); + private static TreeView> treeView(AgentsMapByApplication agentsListsList) { + List> list = agentsListsList.getAgentsListsList(); return new StaticTreeView<>(list); } - @GetMapping(value = "/search-application", params = {"application"}) public TreeView> getAgentsList( @RequestParam("application") String applicationName, @@ -106,4 +106,26 @@ private static TreeView> treeView(AgentsMapByH return new StaticTreeView<>(list); } + @GetMapping(value = "/statistics") + public TreeView> getAllAgentStatistics( + ) { + long timestamp = System.currentTimeMillis(); + AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsStatisticsList( + AgentStatusFilter::accept, + Range.between(timestamp, timestamp) + ); + return treeView(allAgentsList); + } + + @GetMapping(value = "/statistics", params = {"from", "to"}) + public TreeView> getAllAgentStatistics( + @RequestParam("from") long from, + @RequestParam("to") long to + ) { + AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsStatisticsList( + AgentStatusFilter::accept, + Range.between(from, to) + ); + return treeView(allAgentsList); + } } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java index ffe1deff301c..6b12718d8a85 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java @@ -39,4 +39,6 @@ public interface AgentInfoDao { * No ServerMetaData, No JvmInfo */ List getSimpleAgentInfos(List agentIds, long timestamp); + + List getDetailedAgentInfos(List agentIds, long timestamp, boolean withServerMetadata, boolean withJVM); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java index af6f785c41ee..876ab8dec756 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java @@ -125,6 +125,12 @@ public List getAgentInfos(List agentIds, long timestamp) { return getAgentInfos0(agentIds, timestamp, agentInfoResultsExtractor, AgentInfoColumn.simple()); } + @Override + public List getDetailedAgentInfos(List agentIds, long timestamp, boolean withServerMetadata, boolean withJVM) { + return getAgentInfos0(agentIds, timestamp, detailedAgentInfoResultsExtractor, new AgentInfoColumn(true, withServerMetadata, withJVM)); + } + + @Override public List getSimpleAgentInfos(List agentIds, long timestamp) { return getAgentInfos0(agentIds, timestamp, agentInfoResultsExtractor, AgentInfoColumn.simple()); } diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java index 065e0f327a0f..e911aa6fa95c 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java @@ -17,6 +17,7 @@ package com.navercorp.pinpoint.web.service; import com.navercorp.pinpoint.common.server.util.time.Range; +import com.navercorp.pinpoint.web.vo.agent.DetailedAgentInfo; import com.navercorp.pinpoint.web.vo.tree.AgentsMapByApplication; import com.navercorp.pinpoint.web.vo.tree.ApplicationAgentHostList; import com.navercorp.pinpoint.web.vo.tree.AgentsMapByHost; @@ -41,9 +42,9 @@ public interface AgentInfoService { int NO_DURATION = -1; - AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range range); + AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range range); - AgentsMapByHost getAgentsListByApplicationName(AgentStatusFilter filter, String applicationName, Range range); + AgentsMapByApplication getAllAgentsStatisticsList(AgentStatusFilter filter, Range range); AgentsMapByHost getAgentsListByApplicationName(AgentStatusFilter filter, String applicationName, Range range, SortByAgentInfo.Rules sortBy); 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 65ced75d21f9..bf99562243ec 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 @@ -106,7 +106,7 @@ public AgentInfoServiceImpl(AgentEventService agentEventService, } @Override - public AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range range) { + public AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range range) { Objects.requireNonNull(filter, "filter"); List applications = applicationIndexDao.selectAllApplicationNames(); @@ -115,15 +115,26 @@ public AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range r agents.addAll(getAgentsByApplicationName(application.getName(), range.getTo())); } - return AgentsMapByApplication.newAgentsMapByApplication( + return AgentsMapByApplication.newAgentAndStatusMap( filter, agents ); } @Override - public AgentsMapByHost getAgentsListByApplicationName(AgentStatusFilter filter, String applicationName, Range range) { - return getAgentsListByApplicationName(filter, applicationName, range, SortByAgentInfo.Rules.AGENT_ID_ASC); + public AgentsMapByApplication getAllAgentsStatisticsList(AgentStatusFilter filter, Range range) { + Objects.requireNonNull(filter, "filter"); + + List applications = applicationIndexDao.selectAllApplicationNames(); + List agents = new ArrayList<>(); + for (Application application : applications) { + agents.addAll(getDetailedAgentsByApplicationName(application.getName(), range.getTo())); + } + + return AgentsMapByApplication.newDetailedAgentInfoMap( + filter, + agents + ); } @Override @@ -279,6 +290,37 @@ public List getAgentsByApplicationNameWithoutStatus0(String applicati } + public Set getDetailedAgentsByApplicationName(String applicationName, long timestamp) { + List agentInfos = this.getDetailedAgentsByApplicationNameWithoutStatus0(applicationName, timestamp); + + List result = new ArrayList<>(agentInfos.size()); + + AgentStatusQuery query = AgentStatusQuery.buildGenericQuery(agentInfos, DetailedAgentInfo::getAgentInfo, Instant.ofEpochMilli(timestamp)); + List> agentStatus = this.agentLifeCycleDao.getAgentStatus(query); + + for (int i = 0; i < agentStatus.size(); i++) { + Optional status = agentStatus.get(i); + DetailedAgentInfo agentInfo = agentInfos.get(i); + result.add(new DetailedAgentAndStatus(agentInfo, status.orElse(null))); + } + + return new HashSet<>(result); + } + + public List getDetailedAgentsByApplicationNameWithoutStatus0(String applicationName, long timestamp) { + Objects.requireNonNull(applicationName, "applicationName"); + if (timestamp < 0) { + throw new IllegalArgumentException("timestamp must not be less than 0"); + } + + List agentIds = this.applicationIndexDao.selectAgentIds(applicationName); + List agentInfos = this.agentInfoDao.getDetailedAgentInfos(agentIds, timestamp, false, true); + + return agentInfos.stream() + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + @Override public Set getRecentAgentsByApplicationName(String applicationName, long timestamp, long timeDiff) { if (timeDiff > timestamp) { diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/agent/AgentStatusQuery.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/agent/AgentStatusQuery.java index 1a4686bc174f..86d0fdbde31a 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/agent/AgentStatusQuery.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/agent/AgentStatusQuery.java @@ -56,6 +56,10 @@ public static AgentStatusQuery buildQuery(Collection agentInfos, Inst return buildQuery(agentInfos, AgentStatusQuery::apply, timestamp); } + public static AgentStatusQuery buildGenericQuery(Collection agentInfos, Function agentInfoFunction, Instant timestamp) { + return buildQuery(agentInfos, agentInfoFunction.andThen(AgentStatusQuery::apply), timestamp); + } + private static SimpleAgentKey apply(AgentInfo agentInfo) { if (agentInfo == null) { return null; diff --git a/web/src/main/java/com/navercorp/pinpoint/web/vo/tree/AgentsMapByApplication.java b/web/src/main/java/com/navercorp/pinpoint/web/vo/tree/AgentsMapByApplication.java index c24734ae5702..1359a9a95e9c 100644 --- a/web/src/main/java/com/navercorp/pinpoint/web/vo/tree/AgentsMapByApplication.java +++ b/web/src/main/java/com/navercorp/pinpoint/web/vo/tree/AgentsMapByApplication.java @@ -1,45 +1,83 @@ package com.navercorp.pinpoint.web.vo.tree; import com.navercorp.pinpoint.web.vo.agent.AgentAndStatus; +import com.navercorp.pinpoint.web.vo.agent.AgentInfo; import com.navercorp.pinpoint.web.vo.agent.AgentStatusFilter; +import com.navercorp.pinpoint.web.vo.agent.AgentStatus; +import com.navercorp.pinpoint.web.vo.agent.DetailedAgentAndStatus; +import com.navercorp.pinpoint.web.vo.agent.DetailedAgentInfo; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; -public class AgentsMapByApplication { +public class AgentsMapByApplication { - private final InstancesListMap instancesListMap; + private final InstancesListMap instancesListMap; - private AgentsMapByApplication(InstancesListMap instancesListMap) { + private AgentsMapByApplication(InstancesListMap instancesListMap) { this.instancesListMap = Objects.requireNonNull(instancesListMap, "agentsListMap"); } - public List> getAgentsListsList() { + public List> getAgentsListsList() { return new ArrayList<>(instancesListMap.getListMap()); } - public static AgentsMapByApplication newAgentsMapByApplication(AgentStatusFilter filter, - Collection agentCollection) { + public static AgentsMapByApplication newAgentAndStatusMap( + AgentStatusFilter filter, + Collection agentAndStatuses + ) { + return AgentsMapByApplication.newAgentsMapByApplication( + filter, + agentAndStatuses, + AgentAndStatus::getAgentInfo, + AgentAndStatus::getStatus, + Function.identity() + ); + } + + public static AgentsMapByApplication newDetailedAgentInfoMap( + AgentStatusFilter filter, + Collection agentAndStatuses + ) { + return AgentsMapByApplication.newAgentsMapByApplication( + filter, + agentAndStatuses, + DetailedAgentInfo::getAgentInfo, + DetailedAgentAndStatus::getStatus, + DetailedAgentAndStatus::getDetailedAgentInfo + ); + } + + public static AgentsMapByApplication newAgentsMapByApplication( + AgentStatusFilter filter, + Collection agentCollection, + Function agentInfoSupplier, + Function agentStatusSupplier, + Function finisher + ) { Objects.requireNonNull(filter, "filter"); Objects.requireNonNull(agentCollection, "agentCollection"); - InstancesListMapBuilder instancesListMapBuilder = - new InstancesListMapBuilder<>( - AgentsMapByApplication::byApplicationName, + InstancesListMapBuilder instancesListMapBuilder = + new InstancesListMapBuilder( + agentInfoSupplier.andThen(AgentsMapByApplication::byApplicationName), Comparator.naturalOrder(), - SortByAgentInfo.agentIdAsc(AgentAndStatus::getAgentInfo).getComparator(), + SortByAgentInfo.agentIdAsc(agentInfoSupplier).getComparator(), agentCollection ); - instancesListMapBuilder.withFilter((AgentAndStatus a) -> filter.filter(a.getStatus())); - return new AgentsMapByApplication(instancesListMapBuilder.build()); + instancesListMapBuilder.withFilter((I x) -> filter.filter(agentStatusSupplier.apply(x))); + instancesListMapBuilder.withFinisher(finisher); + return new AgentsMapByApplication(instancesListMapBuilder.build()); } - private static String byApplicationName(AgentAndStatus agentAndStatus) { - return agentAndStatus.getAgentInfo().getApplicationName(); + private static String byApplicationName(AgentInfo agentInfo) { + return agentInfo.getApplicationName(); } @Override diff --git a/web/src/test/java/com/navercorp/pinpoint/web/vo/AgentsMapByApplicationTest.java b/web/src/test/java/com/navercorp/pinpoint/web/vo/AgentsMapByApplicationTest.java index aee477f76255..df733bdd0234 100644 --- a/web/src/test/java/com/navercorp/pinpoint/web/vo/AgentsMapByApplicationTest.java +++ b/web/src/test/java/com/navercorp/pinpoint/web/vo/AgentsMapByApplicationTest.java @@ -22,7 +22,7 @@ public void groupByApplicationName() { AgentAndStatus app2Agent2 = createAgentInfo("APP_2", "app2-agent2", "Host22", true); List agentAndStatusList = shuffleAgentInfos(app1Agent1, app1Agent2, app2Agent1, app2Agent2); - AgentsMapByApplication agentsMapByApplication = AgentsMapByApplication.newAgentsMapByApplication(AgentStatusFilter::accept, agentAndStatusList); + AgentsMapByApplication agentsMapByApplication = AgentsMapByApplication.newAgentAndStatusMap(AgentStatusFilter::accept, agentAndStatusList); List> instancesLists = agentsMapByApplication.getAgentsListsList(); Assertions.assertEquals(2, instancesLists.size());