Repository: pinpoint-apm/pinpoint
Issue: Web throws NPE when filtering calls with RPC internal types

When filtering RPC calls on Pinpoint web, NullPointerException is thrown.

This is due to a missing check inside the filtering logic. WAS -> WAS filtering checks each span event for its `ServiceType` and if it is in the RPC range (9000~9999), does an equals check with the span event's `destinationId`. Since RPC internal methods does not have a `destinationId`, while being within the RPC range, NPE is thrown.

Fix needs 2 checks - to check if the span event's ServiceType is set to record statistics, and to check for null `destinationId`.


Changed files:
web/src/main/java/com/navercorp/pinpoint/web/filter/FilterHint.java, web/src/main/java/com/navercorp/pinpoint/web/filter/FromToResponseFilter.java, web/src/main/java/com/navercorp/pinpoint/web/filter/DefaultFilterBuilder.java

diff --git a/web/src/main/java/com/navercorp/pinpoint/web/filter/DefaultFilterBuilder.java b/web/src/main/java/com/navercorp/pinpoint/web/filter/DefaultFilterBuilder.java
index 9a5d2afaa9..e944caa7a5 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/filter/DefaultFilterBuilder.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/filter/DefaultFilterBuilder.java
@@ -149,7 +149,7 @@ public class DefaultFilterBuilder implements FilterBuilder {
         Long fromResponseTime = descriptor.getResponseFrom();
         Long toResponseTime = descriptor.getResponseTo();
         Boolean includeFailed = descriptor.getIncludeException();
-        return new FromToResponseFilter(fromServiceType, fromApplicationName, fromAgentName, toServiceType, toApplicationName, toAgentName,fromResponseTime, toResponseTime, includeFailed, hint);
+        return new FromToResponseFilter(fromServiceType, fromApplicationName, fromAgentName, toServiceType, toApplicationName, toAgentName,fromResponseTime, toResponseTime, includeFailed, hint, this.registry);
     }
 
     private FromToFilter createFromToFilter(FilterDescriptor descriptor) {
diff --git a/web/src/main/java/com/navercorp/pinpoint/web/filter/FilterHint.java b/web/src/main/java/com/navercorp/pinpoint/web/filter/FilterHint.java
index 87ee338fdb..07a776cbd1 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/filter/FilterHint.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/filter/FilterHint.java
@@ -46,6 +46,10 @@ public class FilterHint extends HashMap<String, List<Object>> {
         if (!containApplicationHint(applicationName)) {
             return false;
         }
+        
+        if (endPoint == null) {
+            return false;
+        }
 
         List<Object> list = get(applicationName);
 
diff --git a/web/src/main/java/com/navercorp/pinpoint/web/filter/FromToResponseFilter.java b/web/src/main/java/com/navercorp/pinpoint/web/filter/FromToResponseFilter.java
index 7e18feb8db..f6a3497cbc 100644
--- a/web/src/main/java/com/navercorp/pinpoint/web/filter/FromToResponseFilter.java
+++ b/web/src/main/java/com/navercorp/pinpoint/web/filter/FromToResponseFilter.java
@@ -20,6 +20,7 @@ import java.util.List;
 
 import com.navercorp.pinpoint.common.bo.SpanBo;
 import com.navercorp.pinpoint.common.bo.SpanEventBo;
+import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService;
 import com.navercorp.pinpoint.common.trace.ServiceType;
 import com.navercorp.pinpoint.common.trace.ServiceTypeCategory;
 
@@ -43,8 +44,10 @@ public class FromToResponseFilter implements Filter {
     private final Boolean includeFailed;
 
     private final FilterHint hint;
+    
+    private final ServiceTypeRegistryService registry;
 
-    public FromToResponseFilter(List<ServiceType> fromServiceList, String fromApplicationName, String fromAgentName, List<ServiceType> toServiceList, String toApplicationName, String toAgentName, Long fromResponseTime, Long toResponseTime, Boolean includeFailed, FilterHint hint) {
+    public FromToResponseFilter(List<ServiceType> fromServiceList, String fromApplicationName, String fromAgentName, List<ServiceType> toServiceList, String toApplicationName, String toAgentName, Long fromResponseTime, Long toResponseTime, Boolean includeFailed, FilterHint hint, ServiceTypeRegistryService registry) {
 
         if (fromServiceList == null) {
             throw new NullPointerException("fromServiceList must not be null");
@@ -61,6 +64,9 @@ public class FromToResponseFilter implements Filter {
         if (hint == null) {
             throw new NullPointerException("hint must not be null");
         }
+        if (registry == null) {
+            throw new NullPointerException("registry must not be null");
+        }
 
         this.fromServiceCode = fromServiceList;
         this.fromApplicationName = fromApplicationName;
@@ -74,8 +80,9 @@ public class FromToResponseFilter implements Filter {
         this.toResponseTime = toResponseTime;
         this.includeFailed = includeFailed;
 
-
         this.hint = hint;
+        
+        this.registry = registry;
     }
 
     private boolean checkResponseCondition(long elapsed, boolean hasError) {
@@ -211,8 +218,12 @@ public class FromToResponseFilter implements Filter {
         return false;
     }
 
-    private boolean isRpcClient(short serviceType) {
-        return ServiceTypeCategory.RPC.contains(serviceType);
+    private boolean isRpcClient(short serviceTypeCode) {
+        if (ServiceTypeCategory.RPC.contains(serviceTypeCode)) {
+            ServiceType serviceType = this.registry.findServiceType(serviceTypeCode);
+            return serviceType.isRecordStatistics();
+        }
+        return false;
     }