Repository: pinpoint-apm/pinpoint
Issue: Add time filtering when querying agents for Realtime data
Labels: enhancement

When querying for realtime data such as the active thread chart, servers that are no longer in use are of no interest. These servers are currently displayed as _NOT_FOUND_ and will continue to be displayed until the TTL value set in HBase.

It might be a good idea to set a reasonable time buffer (perhaps a week?) when querying for these agents so that servers that were down for longer than a week does not show up in the active thread chart and confuse everyone.


Issue comments:
Api change affects transaction list queries - reopening issue.

Reopening issue to add configuration option for the duration determining agent inactivity.


Pull request review comments:

Patch that resolved the issue:
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 644bd9dd52bc..e623937fcf0b 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
@@ -38,6 +38,8 @@ public interface AgentInfoService {
 
     Set<AgentInfo> getAgentsByApplicationName(String applicationName, long timestamp);
 
+    Set<AgentInfo> getAgentsByApplicationName(String applicationName, long timestamp, long timeDiff);
+
     AgentInfo getAgentInfo(String agentId, long timestamp);
 
     AgentStatus getAgentStatus(String agentId, long timestamp);
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 4f180b4d82cf..582deca402f2 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
@@ -134,9 +134,23 @@ public ApplicationAgentList getApplicationAgentList(ApplicationAgentList.Key app
 
     @Override
     public Set<AgentInfo> getAgentsByApplicationName(String applicationName, long timestamp) {
+        long timeDiff = timestamp;
+        return this.getAgentsByApplicationName(applicationName, timestamp, timeDiff);
+    }
+
+    @Override
+    public Set<AgentInfo> getAgentsByApplicationName(String applicationName, long timestamp, long timeDiff) {
         if (applicationName == null) {
             throw new NullPointerException("applicationName must not be null");
         }
+        if (timeDiff < 0) {
+            throw new IllegalArgumentException("timeDiff must not be less than 0");
+        }
+        if (timeDiff > timestamp) {
+            throw new IllegalArgumentException("timeDiff must not be greater than timestamp");
+        }
+
+        final long eventTimestampFloor = timestamp - timeDiff;
 
         List<String> agentIds = this.applicationIndexDao.selectAgentIds(applicationName);
         Set<AgentInfo> agentSet = new HashSet<>();
@@ -145,9 +159,12 @@ public Set<AgentInfo> getAgentsByApplicationName(String applicationName, long ti
             // (As we do not yet have a way to accurately record the agent's lifecycle.)
             AgentInfoBo agentInfoBo = this.agentInfoDao.getAgentInfo(agentId, timestamp);
             if (agentInfoBo != null) {
-                AgentInfo agentInfo = new AgentInfo(agentInfoBo);
-                agentInfo.setStatus(this.getAgentStatus(agentId, timestamp));
-                agentSet.add(agentInfo);
+                AgentStatus agentStatus = this.getAgentStatus(agentId, timestamp);
+                if (AgentLifeCycleState.UNKNOWN == agentStatus.getState() || eventTimestampFloor <= agentStatus.getEventTimestamp()) {
+                    AgentInfo agentInfo = new AgentInfo(agentInfoBo);
+                    agentInfo.setStatus(agentStatus);
+                    agentSet.add(agentInfo);
+                }
             }
         }
         return agentSet;
diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java
index ce6340ab7cfb..251844d8d570 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentService.java
@@ -42,7 +42,8 @@ public interface AgentService {
     AgentInfo getAgentInfo(String applicationName, String agentId, long startTimeStamp);
     AgentInfo getAgentInfo(String applicationName, String agentId, long startTimeStamp, boolean checkDB);
 
-    List<AgentInfo> getAgentInfoList(String applicationName);
+    List<AgentInfo> getRecentAgentInfoList(String applicationName);
+    List<AgentInfo> getRecentAgentInfoList(String applicationName, long timeDiff);
 
     boolean isConnected(AgentInfo agentInfo);
 
diff --git a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java
index 241476db44e9..596565e88def 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/service/AgentServiceImpl.java
@@ -51,6 +51,7 @@
 import org.springframework.stereotype.Service;
 
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @author HyunGil Jeong
@@ -61,6 +62,9 @@ public class AgentServiceImpl implements AgentService {
 
     private static final long DEFAULT_FUTURE_TIMEOUT = 3000;
 
+    private static final long DEFAULT_TIME_DIFF_DAYS = 7;
+    private static final long DEFAULT_TIME_DIFF_MS = TimeUnit.MILLISECONDS.convert(DEFAULT_TIME_DIFF_DAYS, TimeUnit.DAYS);
+
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
     @Autowired
@@ -135,12 +139,17 @@ public AgentInfo getAgentInfo(String applicationName, String agentId, long start
     }
 
     @Override
-    public List<AgentInfo> getAgentInfoList(String applicationName) {
+    public List<AgentInfo> getRecentAgentInfoList(String applicationName) {
+        return this.getRecentAgentInfoList(applicationName, DEFAULT_TIME_DIFF_MS);
+    }
+
+    @Override
+    public List<AgentInfo> getRecentAgentInfoList(String applicationName, long timeDiff) {
         List<AgentInfo> agentInfoList = new ArrayList<>();
 
         long currentTime = System.currentTimeMillis();
 
-        Set<AgentInfo> agentInfos = agentInfoService.getAgentsByApplicationName(applicationName, currentTime);
+        Set<AgentInfo> agentInfos = agentInfoService.getAgentsByApplicationName(applicationName, currentTime, timeDiff);
         for (AgentInfo agentInfo : agentInfos) {
             ListUtils.addIfValueNotNull(agentInfoList, agentInfo);
         }
diff --git a/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadCountResponseAggregator.java b/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadCountResponseAggregator.java
index 3b12fd75711a..b048ebbe9796 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadCountResponseAggregator.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/websocket/ActiveThreadCountResponseAggregator.java
@@ -110,7 +110,7 @@ public void addWebSocketSession(WebSocketSession webSocketSession) {
 
         logger.info("addWebSocketSession. applicationName:{}, webSocketSession:{}", applicationName, webSocketSession);
 
-        List<AgentInfo> agentInfoList = agentService.getAgentInfoList(applicationName);
+        List<AgentInfo> agentInfoList = agentService.getRecentAgentInfoList(applicationName);
         synchronized (workerManagingLock) {
             if (isStopped) {
                 return;
diff --git a/web/src/main/java/com/navercorp/pinpoint/web/websocket/WorkerActiveManager.java b/web/src/main/java/com/navercorp/pinpoint/web/websocket/WorkerActiveManager.java
index d6a609c48c5f..1f614a2256fb 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/websocket/WorkerActiveManager.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/websocket/WorkerActiveManager.java
@@ -148,7 +148,7 @@ public void run(Timeout timeout) throws Exception {
             logger.info("AgentCheckTimerTask started.");
 
             try {
-                List<AgentInfo> agentInfoList = agentService.getAgentInfoList(applicationName);
+                List<AgentInfo> agentInfoList = agentService.getRecentAgentInfoList(applicationName);
                 for (AgentInfo agentInfo : agentInfoList) {
                     String agentId = agentInfo.getAgentId();
                     if (defaultAgentIdList.contains(agentId)) {


Test patch: