Skip to content

Commit 5c9fb5e

Browse files
committed
[#9641] Add new API for agent statistics
1 parent 81fb12b commit 5c9fb5e

File tree

9 files changed

+156
-29
lines changed

9 files changed

+156
-29
lines changed

web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentInfoController.java

+16-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.navercorp.pinpoint.web.vo.timeline.inspector.InspectorTimeline;
3939
import com.navercorp.pinpoint.web.view.tree.SimpleTreeView;
4040
import com.navercorp.pinpoint.web.view.tree.TreeView;
41+
import com.navercorp.pinpoint.web.vo.tree.SortByAgentInfo;
4142
import org.springframework.http.HttpStatus;
4243
import org.springframework.web.bind.annotation.GetMapping;
4344
import org.springframework.web.bind.annotation.RequestMapping;
@@ -59,6 +60,8 @@ public class AgentInfoController {
5960

6061
private final AgentEventService agentEventService;
6162

63+
private SortByAgentInfo.Rules DEFAULT_SORTBY = SortByAgentInfo.Rules.AGENT_ID_ASC;
64+
6265
public AgentInfoController(AgentInfoService agentInfoService, AgentEventService agentEventService) {
6366
this.agentInfoService = Objects.requireNonNull(agentInfoService, "agentInfoService");
6467
this.agentEventService = Objects.requireNonNull(agentEventService, "agentEventService");
@@ -76,7 +79,7 @@ public TreeView<TreeNode<AgentAndStatus>> getAgentList(
7679
@RequestParam("to") long to) {
7780
AgentStatusFilter filter = new DefaultAgentStatusFilter(from);
7881
long timestamp = to;
79-
AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsList(filter, Range.between(from, to));
82+
AgentsMapByApplication<AgentAndStatus> allAgentsList = this.agentInfoService.getAllAgentsList(filter, Range.between(from, to));
8083
return treeView(allAgentsList);
8184
}
8285

@@ -88,7 +91,7 @@ public TreeView<TreeNode<AgentAndStatus>> getAgentList(
8891
return treeView(allAgentsList);
8992
}
9093

91-
private static TreeView<TreeNode<AgentAndStatus>> treeView(AgentsMapByApplication agentsListsList) {
94+
private static TreeView<TreeNode<AgentAndStatus>> treeView(AgentsMapByApplication<AgentAndStatus> agentsListsList) {
9295
List<InstancesList<AgentAndStatus>> list = agentsListsList.getAgentsListsList();
9396
return new SimpleTreeView<>(list, InstancesList::getGroupName, InstancesList::getInstancesList);
9497
}
@@ -108,7 +111,12 @@ public TreeView<TreeNode<AgentStatusAndLink>> getAgentList(
108111
new DefaultAgentStatusFilter(from)
109112
);
110113
long timestamp = to;
111-
AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(currentRunFilter, applicationName, Range.between(from, to));
114+
AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(
115+
currentRunFilter,
116+
applicationName,
117+
Range.between(from, to),
118+
DEFAULT_SORTBY
119+
);
112120
return treeView(list);
113121
}
114122

@@ -119,7 +127,11 @@ public TreeView<TreeNode<AgentStatusAndLink>> getAgentList(
119127
AgentStatusFilter runningAgentFilter = new AgentStatusFilterChain(
120128
AgentStatusFilter::filterRunning
121129
);
122-
AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(runningAgentFilter, applicationName, Range.between(timestamp, timestamp));
130+
AgentsMapByHost list = this.agentInfoService.getAgentsListByApplicationName(runningAgentFilter,
131+
applicationName,
132+
Range.between(timestamp, timestamp),
133+
DEFAULT_SORTBY
134+
);
123135
return treeView(list);
124136
}
125137

web/src/main/java/com/navercorp/pinpoint/web/authorization/controller/AgentListController.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.navercorp.pinpoint.web.vo.agent.AgentStatusFilterChain;
1010
import com.navercorp.pinpoint.web.vo.agent.AgentStatusAndLink;
1111
import com.navercorp.pinpoint.web.vo.agent.DefaultAgentStatusFilter;
12+
import com.navercorp.pinpoint.web.vo.agent.DetailedAgentInfo;
1213
import com.navercorp.pinpoint.web.vo.tree.InstancesList;
1314
import com.navercorp.pinpoint.web.vo.tree.AgentsMapByApplication;
1415
import com.navercorp.pinpoint.web.vo.tree.AgentsMapByHost;
@@ -51,19 +52,18 @@ public TreeView<InstancesList<AgentAndStatus>> getAllAgentsList(
5152
@RequestParam("from") long from,
5253
@RequestParam("to") long to) {
5354
AgentStatusFilter filter = new DefaultAgentStatusFilter(from);
54-
AgentsMapByApplication allAgentsList = this.agentInfoService.getAllAgentsList(
55+
AgentsMapByApplication<AgentAndStatus> allAgentsList = this.agentInfoService.getAllAgentsList(
5556
filter,
5657
Range.between(from, to)
5758
);
5859
return treeView(allAgentsList);
5960
}
6061

61-
private static TreeView<InstancesList<AgentAndStatus>> treeView(AgentsMapByApplication agentsListsList) {
62-
List<InstancesList<AgentAndStatus>> list = agentsListsList.getAgentsListsList();
62+
private static <T> TreeView<InstancesList<T>> treeView(AgentsMapByApplication<T> agentsListsList) {
63+
List<InstancesList<T>> list = agentsListsList.getAgentsListsList();
6364
return new StaticTreeView<>(list);
6465
}
6566

66-
6767
@GetMapping(value = "/search-application", params = {"application"})
6868
public TreeView<InstancesList<AgentStatusAndLink>> getAgentsList(
6969
@RequestParam("application") String applicationName,
@@ -106,4 +106,26 @@ private static TreeView<InstancesList<AgentStatusAndLink>> treeView(AgentsMapByH
106106
return new StaticTreeView<>(list);
107107
}
108108

109+
@GetMapping(value = "/statistics")
110+
public TreeView<InstancesList<DetailedAgentInfo>> getAllAgentStatistics(
111+
) {
112+
long timestamp = System.currentTimeMillis();
113+
AgentsMapByApplication<DetailedAgentInfo> allAgentsList = this.agentInfoService.getAllAgentsStatisticsList(
114+
AgentStatusFilter::accept,
115+
Range.between(timestamp, timestamp)
116+
);
117+
return treeView(allAgentsList);
118+
}
119+
120+
@GetMapping(value = "/statistics", params = {"from", "to"})
121+
public TreeView<InstancesList<DetailedAgentInfo>> getAllAgentStatistics(
122+
@RequestParam("from") long from,
123+
@RequestParam("to") long to
124+
) {
125+
AgentsMapByApplication<DetailedAgentInfo> allAgentsList = this.agentInfoService.getAllAgentsStatisticsList(
126+
AgentStatusFilter::accept,
127+
Range.between(from, to)
128+
);
129+
return treeView(allAgentsList);
130+
}
109131
}

web/src/main/java/com/navercorp/pinpoint/web/dao/AgentInfoDao.java

+2
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@ public interface AgentInfoDao {
3939
* No ServerMetaData, No JvmInfo
4040
*/
4141
List<AgentInfo> getSimpleAgentInfos(List<String> agentIds, long timestamp);
42+
43+
List<DetailedAgentInfo> getDetailedAgentInfos(List<String> agentIds, long timestamp, boolean withServerMetadata, boolean withJVM);
4244
}

web/src/main/java/com/navercorp/pinpoint/web/dao/hbase/HbaseAgentInfoDao.java

+6
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ public List<AgentInfo> getAgentInfos(List<String> agentIds, long timestamp) {
125125
return getAgentInfos0(agentIds, timestamp, agentInfoResultsExtractor, AgentInfoColumn.simple());
126126
}
127127

128+
@Override
129+
public List<DetailedAgentInfo> getDetailedAgentInfos(List<String> agentIds, long timestamp, boolean withServerMetadata, boolean withJVM) {
130+
return getAgentInfos0(agentIds, timestamp, detailedAgentInfoResultsExtractor, new AgentInfoColumn(true, withServerMetadata, withJVM));
131+
}
132+
133+
@Override
128134
public List<AgentInfo> getSimpleAgentInfos(List<String> agentIds, long timestamp) {
129135
return getAgentInfos0(agentIds, timestamp, agentInfoResultsExtractor, AgentInfoColumn.simple());
130136
}

web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoService.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.navercorp.pinpoint.web.service;
1818

1919
import com.navercorp.pinpoint.common.server.util.time.Range;
20+
import com.navercorp.pinpoint.web.vo.agent.DetailedAgentInfo;
2021
import com.navercorp.pinpoint.web.vo.tree.AgentsMapByApplication;
2122
import com.navercorp.pinpoint.web.vo.tree.ApplicationAgentHostList;
2223
import com.navercorp.pinpoint.web.vo.tree.AgentsMapByHost;
@@ -41,9 +42,9 @@ public interface AgentInfoService {
4142

4243
int NO_DURATION = -1;
4344

44-
AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range range);
45+
AgentsMapByApplication<AgentAndStatus> getAllAgentsList(AgentStatusFilter filter, Range range);
4546

46-
AgentsMapByHost getAgentsListByApplicationName(AgentStatusFilter filter, String applicationName, Range range);
47+
AgentsMapByApplication<DetailedAgentInfo> getAllAgentsStatisticsList(AgentStatusFilter filter, Range range);
4748

4849
AgentsMapByHost getAgentsListByApplicationName(AgentStatusFilter filter, String applicationName, Range range, SortByAgentInfo.Rules sortBy);
4950

web/src/main/java/com/navercorp/pinpoint/web/service/AgentInfoServiceImpl.java

+46-4
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public AgentInfoServiceImpl(AgentEventService agentEventService,
106106
}
107107

108108
@Override
109-
public AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range range) {
109+
public AgentsMapByApplication<AgentAndStatus> getAllAgentsList(AgentStatusFilter filter, Range range) {
110110
Objects.requireNonNull(filter, "filter");
111111

112112
List<Application> applications = applicationIndexDao.selectAllApplicationNames();
@@ -115,15 +115,26 @@ public AgentsMapByApplication getAllAgentsList(AgentStatusFilter filter, Range r
115115
agents.addAll(getAgentsByApplicationName(application.getName(), range.getTo()));
116116
}
117117

118-
return AgentsMapByApplication.newAgentsMapByApplication(
118+
return AgentsMapByApplication.newAgentAndStatusMap(
119119
filter,
120120
agents
121121
);
122122
}
123123

124124
@Override
125-
public AgentsMapByHost getAgentsListByApplicationName(AgentStatusFilter filter, String applicationName, Range range) {
126-
return getAgentsListByApplicationName(filter, applicationName, range, SortByAgentInfo.Rules.AGENT_ID_ASC);
125+
public AgentsMapByApplication<DetailedAgentInfo> getAllAgentsStatisticsList(AgentStatusFilter filter, Range range) {
126+
Objects.requireNonNull(filter, "filter");
127+
128+
List<Application> applications = applicationIndexDao.selectAllApplicationNames();
129+
List<DetailedAgentAndStatus> agents = new ArrayList<>();
130+
for (Application application : applications) {
131+
agents.addAll(getDetailedAgentsByApplicationName(application.getName(), range.getTo()));
132+
}
133+
134+
return AgentsMapByApplication.newDetailedAgentInfoMap(
135+
filter,
136+
agents
137+
);
127138
}
128139

129140
@Override
@@ -279,6 +290,37 @@ public List<AgentInfo> getAgentsByApplicationNameWithoutStatus0(String applicati
279290

280291
}
281292

293+
public Set<DetailedAgentAndStatus> getDetailedAgentsByApplicationName(String applicationName, long timestamp) {
294+
List<DetailedAgentInfo> agentInfos = this.getDetailedAgentsByApplicationNameWithoutStatus0(applicationName, timestamp);
295+
296+
List<DetailedAgentAndStatus> result = new ArrayList<>(agentInfos.size());
297+
298+
AgentStatusQuery query = AgentStatusQuery.buildGenericQuery(agentInfos, DetailedAgentInfo::getAgentInfo, Instant.ofEpochMilli(timestamp));
299+
List<Optional<AgentStatus>> agentStatus = this.agentLifeCycleDao.getAgentStatus(query);
300+
301+
for (int i = 0; i < agentStatus.size(); i++) {
302+
Optional<AgentStatus> status = agentStatus.get(i);
303+
DetailedAgentInfo agentInfo = agentInfos.get(i);
304+
result.add(new DetailedAgentAndStatus(agentInfo, status.orElse(null)));
305+
}
306+
307+
return new HashSet<>(result);
308+
}
309+
310+
public List<DetailedAgentInfo> getDetailedAgentsByApplicationNameWithoutStatus0(String applicationName, long timestamp) {
311+
Objects.requireNonNull(applicationName, "applicationName");
312+
if (timestamp < 0) {
313+
throw new IllegalArgumentException("timestamp must not be less than 0");
314+
}
315+
316+
List<String> agentIds = this.applicationIndexDao.selectAgentIds(applicationName);
317+
List<DetailedAgentInfo> agentInfos = this.agentInfoDao.getDetailedAgentInfos(agentIds, timestamp, false, true);
318+
319+
return agentInfos.stream()
320+
.filter(Objects::nonNull)
321+
.collect(Collectors.toList());
322+
}
323+
282324
@Override
283325
public Set<AgentAndStatus> getRecentAgentsByApplicationName(String applicationName, long timestamp, long timeDiff) {
284326
if (timeDiff > timestamp) {

web/src/main/java/com/navercorp/pinpoint/web/vo/agent/AgentStatusQuery.java

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public static AgentStatusQuery buildQuery(Collection<AgentInfo> agentInfos, Inst
5656
return buildQuery(agentInfos, AgentStatusQuery::apply, timestamp);
5757
}
5858

59+
public static <T> AgentStatusQuery buildGenericQuery(Collection<T> agentInfos, Function<T, AgentInfo> agentInfoFunction, Instant timestamp) {
60+
return buildQuery(agentInfos, agentInfoFunction.andThen(AgentStatusQuery::apply), timestamp);
61+
}
62+
5963
private static SimpleAgentKey apply(AgentInfo agentInfo) {
6064
if (agentInfo == null) {
6165
return null;

web/src/main/java/com/navercorp/pinpoint/web/vo/tree/AgentsMapByApplication.java

+52-14
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,83 @@
11
package com.navercorp.pinpoint.web.vo.tree;
22

33
import com.navercorp.pinpoint.web.vo.agent.AgentAndStatus;
4+
import com.navercorp.pinpoint.web.vo.agent.AgentInfo;
45
import com.navercorp.pinpoint.web.vo.agent.AgentStatusFilter;
6+
import com.navercorp.pinpoint.web.vo.agent.AgentStatus;
7+
import com.navercorp.pinpoint.web.vo.agent.DetailedAgentAndStatus;
8+
import com.navercorp.pinpoint.web.vo.agent.DetailedAgentInfo;
59

610
import java.util.ArrayList;
711
import java.util.Collection;
812
import java.util.Comparator;
913
import java.util.List;
1014
import java.util.Objects;
15+
import java.util.function.Function;
16+
import java.util.function.Predicate;
1117

12-
public class AgentsMapByApplication {
18+
public class AgentsMapByApplication<T> {
1319

14-
private final InstancesListMap<AgentAndStatus> instancesListMap;
20+
private final InstancesListMap<T> instancesListMap;
1521

16-
private AgentsMapByApplication(InstancesListMap<AgentAndStatus> instancesListMap) {
22+
private AgentsMapByApplication(InstancesListMap<T> instancesListMap) {
1723
this.instancesListMap = Objects.requireNonNull(instancesListMap, "agentsListMap");
1824
}
1925

20-
public List<InstancesList<AgentAndStatus>> getAgentsListsList() {
26+
public List<InstancesList<T>> getAgentsListsList() {
2127
return new ArrayList<>(instancesListMap.getListMap());
2228
}
2329

24-
public static AgentsMapByApplication newAgentsMapByApplication(AgentStatusFilter filter,
25-
Collection<AgentAndStatus> agentCollection) {
30+
public static AgentsMapByApplication<AgentAndStatus> newAgentAndStatusMap(
31+
AgentStatusFilter filter,
32+
Collection<AgentAndStatus> agentAndStatuses
33+
) {
34+
return AgentsMapByApplication.newAgentsMapByApplication(
35+
filter,
36+
agentAndStatuses,
37+
AgentAndStatus::getAgentInfo,
38+
AgentAndStatus::getStatus,
39+
Function.identity()
40+
);
41+
}
42+
43+
public static AgentsMapByApplication<DetailedAgentInfo> newDetailedAgentInfoMap(
44+
AgentStatusFilter filter,
45+
Collection<DetailedAgentAndStatus> agentAndStatuses
46+
) {
47+
return AgentsMapByApplication.newAgentsMapByApplication(
48+
filter,
49+
agentAndStatuses,
50+
DetailedAgentInfo::getAgentInfo,
51+
DetailedAgentAndStatus::getStatus,
52+
DetailedAgentAndStatus::getDetailedAgentInfo
53+
);
54+
}
55+
56+
public static <I, T> AgentsMapByApplication<T> newAgentsMapByApplication(
57+
AgentStatusFilter filter,
58+
Collection<I> agentCollection,
59+
Function<T, AgentInfo> agentInfoSupplier,
60+
Function<I, AgentStatus> agentStatusSupplier,
61+
Function<I, T> finisher
62+
) {
2663
Objects.requireNonNull(filter, "filter");
2764
Objects.requireNonNull(agentCollection, "agentCollection");
2865

29-
InstancesListMapBuilder<AgentAndStatus, AgentAndStatus> instancesListMapBuilder =
30-
new InstancesListMapBuilder<>(
31-
AgentsMapByApplication::byApplicationName,
66+
InstancesListMapBuilder<I, T> instancesListMapBuilder =
67+
new InstancesListMapBuilder<I, T>(
68+
agentInfoSupplier.andThen(AgentsMapByApplication::byApplicationName),
3269
Comparator.naturalOrder(),
33-
SortByAgentInfo.agentIdAsc(AgentAndStatus::getAgentInfo).getComparator(),
70+
SortByAgentInfo.agentIdAsc(agentInfoSupplier).getComparator(),
3471
agentCollection
3572
);
3673

37-
instancesListMapBuilder.withFilter((AgentAndStatus a) -> filter.filter(a.getStatus()));
38-
return new AgentsMapByApplication(instancesListMapBuilder.build());
74+
instancesListMapBuilder.withFilter((I x) -> filter.filter(agentStatusSupplier.apply(x)));
75+
instancesListMapBuilder.withFinisher(finisher);
76+
return new AgentsMapByApplication<T>(instancesListMapBuilder.build());
3977
}
4078

41-
private static String byApplicationName(AgentAndStatus agentAndStatus) {
42-
return agentAndStatus.getAgentInfo().getApplicationName();
79+
private static String byApplicationName(AgentInfo agentInfo) {
80+
return agentInfo.getApplicationName();
4381
}
4482

4583
@Override

web/src/test/java/com/navercorp/pinpoint/web/vo/AgentsMapByApplicationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public void groupByApplicationName() {
2222
AgentAndStatus app2Agent2 = createAgentInfo("APP_2", "app2-agent2", "Host22", true);
2323
List<AgentAndStatus> agentAndStatusList = shuffleAgentInfos(app1Agent1, app1Agent2, app2Agent1, app2Agent2);
2424

25-
AgentsMapByApplication agentsMapByApplication = AgentsMapByApplication.newAgentsMapByApplication(AgentStatusFilter::accept, agentAndStatusList);
25+
AgentsMapByApplication<AgentAndStatus> agentsMapByApplication = AgentsMapByApplication.newAgentAndStatusMap(AgentStatusFilter::accept, agentAndStatusList);
2626
List<InstancesList<AgentAndStatus>> instancesLists = agentsMapByApplication.getAgentsListsList();
2727

2828
Assertions.assertEquals(2, instancesLists.size());

0 commit comments

Comments
 (0)