You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ji...@apache.org on 2020/07/29 23:12:35 UTC

[incubator-pinot] branch anomalies-pagination created (now b4e0733)

This is an automated email from the ASF dual-hosted git repository.

jihao pushed a change to branch anomalies-pagination
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git.


      at b4e0733  add java docs

This branch includes the following new commits:

     new 39fcef4  new anomalies endpoint
     new d37df19  anomaly searcher
     new b4e0733  add java docs

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org


[incubator-pinot] 02/03: anomaly searcher

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jihao pushed a commit to branch anomalies-pagination
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git

commit d37df19fe9baa1633499a5db30c88a75e851c212
Author: Jihao Zhang <ji...@linkedin.com>
AuthorDate: Wed Jul 29 16:06:53 2020 -0700

    anomaly searcher
---
 .../thirdeye/constant/AnomalyFeedbackType.java     |  2 +-
 .../v2/anomalies/AnomalySearchFilter.java          | 18 ++++++++++-----
 .../v2/anomalies/AnomalySearchResource.java        |  8 +++----
 .../resources/v2/anomalies/AnomalySearcher.java    | 26 +++++++++++++++++-----
 .../datalayer/entity/MergedAnomalyResultIndex.java |  6 ++---
 .../src/main/resources/schema/create-schema.sql    |  2 +-
 6 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/constant/AnomalyFeedbackType.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/constant/AnomalyFeedbackType.java
index c6c7bfa..93675dd 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/constant/AnomalyFeedbackType.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/constant/AnomalyFeedbackType.java
@@ -47,4 +47,4 @@ public enum AnomalyFeedbackType {
   public boolean isUnresolved() {
     return this.equals(NO_FEEDBACK);
   }
-}
+}
\ No newline at end of file
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
index 1ff7de8..fbc17e8 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
@@ -9,11 +9,12 @@ public class AnomalySearchFilter {
   private final List<String> detectionNames;
   private final List<String> metrics;
   private final List<String> datasets;
-  private final long startTime;
-  private final long endTime;
+  private final List<Long> anomalyIds;
+  private final Long startTime;
+  private final Long endTime;
 
-  public AnomalySearchFilter(long startTime, long endTime, List<String> feedbacks, List<String> subscriptionGroups, List<String> detectionNames,
-      List<String> metrics, List<String> datasets) {
+  public AnomalySearchFilter(Long startTime, Long endTime, List<String> feedbacks, List<String> subscriptionGroups, List<String> detectionNames,
+      List<String> metrics, List<String> datasets, List<Long> anomalyIds) {
     this.feedbacks = feedbacks;
     this.subscriptionGroups = subscriptionGroups;
     this.detectionNames = detectionNames;
@@ -21,13 +22,14 @@ public class AnomalySearchFilter {
     this.datasets = datasets;
     this.startTime = startTime;
     this.endTime = endTime;
+    this.anomalyIds = anomalyIds;
   }
 
-  public long getStartTime() {
+  public Long getStartTime() {
     return startTime;
   }
 
-  public long getEndTime() {
+  public Long getEndTime() {
     return endTime;
   }
 
@@ -50,4 +52,8 @@ public class AnomalySearchFilter {
   public List<String> getDatasets() {
     return datasets;
   }
+
+  public List<Long> getAnomalyIds() {
+    return anomalyIds;
+  }
 }
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
index adfa5f9..74772a6 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
@@ -28,13 +28,13 @@ public class AnomalySearchResource {
   @Produces(MediaType.APPLICATION_JSON)
   @ApiOperation("Search and paginate anomalies according to the parameters")
   public Response findAlerts(@QueryParam("limit") @DefaultValue("10") int limit,
-      @QueryParam("offset") @DefaultValue("0") int offset, @QueryParam("startTime") long startTime,
-      @QueryParam("endTime") long endTime, @QueryParam("feedbackStatus") List<String> feedbacks,
+      @QueryParam("offset") @DefaultValue("0") int offset, @QueryParam("startTime") Long startTime,
+      @QueryParam("endTime") Long endTime, @QueryParam("feedbackStatus") List<String> feedbacks,
       @QueryParam("subscriptionGroup") List<String> subscriptionGroups,
       @QueryParam("detectionName") List<String> detectionNames, @QueryParam("metric") List<String> metrics,
-      @QueryParam("dataset") List<String> datasets) {
+      @QueryParam("dataset") List<String> datasets, @QueryParam("anomalyId") List<Long> anomalyIds) {
     AnomalySearchFilter searchFilter =
-        new AnomalySearchFilter(startTime, endTime, feedbacks, subscriptionGroups, detectionNames, metrics, datasets);
+        new AnomalySearchFilter(startTime, endTime, feedbacks, subscriptionGroups, detectionNames, metrics, datasets, anomalyIds);
     return Response.ok().entity(this.anomalySearcher.search(searchFilter, limit, offset)).build();
   }
 }
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
index 6efad8f..bc29228 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableMap;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -13,6 +14,7 @@ import org.apache.pinot.thirdeye.constant.AnomalyFeedbackType;
 import org.apache.pinot.thirdeye.datalayer.bao.DetectionAlertConfigManager;
 import org.apache.pinot.thirdeye.datalayer.bao.DetectionConfigManager;
 import org.apache.pinot.thirdeye.datalayer.bao.MergedAnomalyResultManager;
+import org.apache.pinot.thirdeye.datalayer.dto.AbstractDTO;
 import org.apache.pinot.thirdeye.datalayer.dto.MergedAnomalyResultDTO;
 import org.apache.pinot.thirdeye.datalayer.pojo.DetectionConfigBean;
 import org.apache.pinot.thirdeye.datalayer.util.Predicate;
@@ -41,9 +43,13 @@ public class AnomalySearcher {
    * @return the result
    */
   public Map<String, Object> search(AnomalySearchFilter searchFilter, int limit, int offset) {
-    Predicate predicate = Predicate.AND(Predicate.LT("startTime", searchFilter.getEndTime()),
-        Predicate.GT("endTime", searchFilter.getStartTime()));
-//, Predicate.NEQ("isChild", false)
+    Predicate predicate = Predicate.EQ("child", false);
+    if (searchFilter.getStartTime() != null) {
+      predicate = Predicate.AND(predicate, Predicate.LT("startTime", searchFilter.getEndTime()));
+    }
+    if (searchFilter.getEndTime() != null) {
+      predicate = Predicate.AND(predicate, Predicate.GT("endTime", searchFilter.getStartTime()));
+    }
     // search by detections or subscription groups
     Set<Long> detectionConfigIds = new HashSet<>();
     Set<Long> subscribedDetectionConfigIds = new HashSet<>();
@@ -89,13 +95,20 @@ public class AnomalySearcher {
     if (!searchFilter.getMetrics().isEmpty()) {
       predicate = Predicate.AND(predicate, Predicate.IN("metric", searchFilter.getMetrics().toArray()));
     }
+    // search by ids
+    if (!searchFilter.getAnomalyIds().isEmpty()) {
+      predicate = Predicate.AND(predicate, Predicate.IN("baseId", searchFilter.getAnomalyIds().toArray()));
+    }
 
     long count;
     List<MergedAnomalyResultDTO> results;
     if (searchFilter.getFeedbacks().isEmpty()) {
-      List<Long> anomalyIds = this.anomalyDAO.findIdsByPredicate(predicate);
+      List<Long> anomalyIds = this.anomalyDAO.findIdsByPredicate(predicate)
+          .stream()
+          .sorted(Comparator.reverseOrder())
+          .collect(Collectors.toList());
       count = anomalyIds.size();
-      results = this.anomalyDAO.findByIds(paginateResults(anomalyIds, offset, limit));
+      results = anomalyIds.isEmpty() ? Collections.emptyList() : this.anomalyDAO.findByIds(paginateResults(anomalyIds, offset, limit));
     } else {
       // filter by feedback types
       List<MergedAnomalyResultDTO> anomalies = this.anomalyDAO.findByPredicate(predicate);
@@ -104,6 +117,7 @@ public class AnomalySearcher {
       results = anomalies.stream()
           .filter(anomaly -> (anomaly.getFeedback() == null && feedbackFilters.contains(NO_FEEDBACK)) || (
               anomaly.getFeedback() != null && feedbackFilters.contains(anomaly.getFeedback().getFeedbackType())))
+          .sorted(Comparator.comparingLong(AbstractDTO::getId).reversed())
           .collect(Collectors.toList());
       count = results.size();
       results = paginateResults(results, offset, limit);
@@ -111,7 +125,7 @@ public class AnomalySearcher {
     return ImmutableMap.of("count", count, "limit", limit, "offset", offset, "elements", results);
   }
 
-  private  <T> List<T> paginateResults(List<T> list, int offset, int limit) {
+  private <T> List<T> paginateResults(List<T> list, int offset, int limit) {
     if (offset > list.size()) {
       // requested page is out of bound
       return Collections.emptyList();
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java
index d5941d9..cfa5c68 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java
@@ -35,7 +35,7 @@ public class MergedAnomalyResultIndex extends AbstractIndexEntity {
   String metric;
   DimensionMap dimensions;
   boolean notified;
-  boolean isChild;
+  boolean child;
 
   public long getDetectionConfigId() {
     return detectionConfigId;
@@ -118,10 +118,10 @@ public class MergedAnomalyResultIndex extends AbstractIndexEntity {
   }
 
   public boolean isChild() {
-    return isChild;
+    return child;
   }
 
   public void setChild(boolean child) {
-    isChild = child;
+    this.child = child;
   }
 }
diff --git a/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql b/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql
index 88c74a1..8454348 100644
--- a/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql
+++ b/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql
@@ -110,7 +110,7 @@ create table if not exists merged_anomaly_result_index (
     base_id bigint(20) not null,
     create_time timestamp,
     update_time timestamp default current_timestamp,
-    is_child boolean,
+    child boolean,
     version int(10)
 ) ENGINE=InnoDB;
 create index merged_anomaly_result_function_idx on merged_anomaly_result_index(function_id);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org


[incubator-pinot] 01/03: new anomalies endpoint

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jihao pushed a commit to branch anomalies-pagination
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git

commit 39fcef438b63f71cfbc4d083972bff2a92b8b22b
Author: Jihao Zhang <ji...@linkedin.com>
AuthorDate: Wed Jul 22 14:22:33 2020 -0700

    new anomalies endpoint
---
 .../dashboard/ThirdEyeDashboardApplication.java    |   2 +
 .../v2/anomalies/AnomalySearchFilter.java          |  53 +++++++++
 .../v2/anomalies/AnomalySearchResource.java        |  40 +++++++
 .../resources/v2/anomalies/AnomalySearcher.java    | 121 +++++++++++++++++++++
 .../datalayer/entity/MergedAnomalyResultIndex.java |   9 ++
 .../src/main/resources/schema/create-schema.sql    |   1 +
 6 files changed, 226 insertions(+)

diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/ThirdEyeDashboardApplication.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/ThirdEyeDashboardApplication.java
index c3decbc..20e547a 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/ThirdEyeDashboardApplication.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/ThirdEyeDashboardApplication.java
@@ -59,6 +59,7 @@ import org.apache.pinot.thirdeye.dashboard.resources.v2.RootCauseMetricResource;
 import org.apache.pinot.thirdeye.dashboard.resources.v2.RootCauseResource;
 import org.apache.pinot.thirdeye.dashboard.resources.v2.RootCauseSessionResource;
 import org.apache.pinot.thirdeye.api.user.dashboard.UserDashboardResource;
+import org.apache.pinot.thirdeye.dashboard.resources.v2.anomalies.AnomalySearchResource;
 import org.apache.pinot.thirdeye.dashboard.resources.v2.rootcause.DefaultEntityFormatter;
 import org.apache.pinot.thirdeye.dashboard.resources.v2.rootcause.FormatterLoader;
 import org.apache.pinot.thirdeye.dataset.DatasetAutoOnboardResource;
@@ -188,6 +189,7 @@ public class ThirdEyeDashboardApplication
         config.getAlertOnboardingPermitPerSecond()));
     env.jersey().register(new SqlDataSourceResource());
     env.jersey().register(new AlertResource());
+    env.jersey().register(new AnomalySearchResource());
 
     TimeSeriesLoader timeSeriesLoader = new DefaultTimeSeriesLoader(
         DAO_REGISTRY.getMetricConfigDAO(), DAO_REGISTRY.getDatasetConfigDAO(),
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
new file mode 100644
index 0000000..1ff7de8
--- /dev/null
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
@@ -0,0 +1,53 @@
+package org.apache.pinot.thirdeye.dashboard.resources.v2.anomalies;
+
+import java.util.List;
+
+
+public class AnomalySearchFilter {
+  private final List<String> feedbacks;
+  private final List<String> subscriptionGroups;
+  private final List<String> detectionNames;
+  private final List<String> metrics;
+  private final List<String> datasets;
+  private final long startTime;
+  private final long endTime;
+
+  public AnomalySearchFilter(long startTime, long endTime, List<String> feedbacks, List<String> subscriptionGroups, List<String> detectionNames,
+      List<String> metrics, List<String> datasets) {
+    this.feedbacks = feedbacks;
+    this.subscriptionGroups = subscriptionGroups;
+    this.detectionNames = detectionNames;
+    this.metrics = metrics;
+    this.datasets = datasets;
+    this.startTime = startTime;
+    this.endTime = endTime;
+  }
+
+  public long getStartTime() {
+    return startTime;
+  }
+
+  public long getEndTime() {
+    return endTime;
+  }
+
+  public List<String> getFeedbacks() {
+    return feedbacks;
+  }
+
+  public List<String> getSubscriptionGroups() {
+    return subscriptionGroups;
+  }
+
+  public List<String> getDetectionNames() {
+    return detectionNames;
+  }
+
+  public List<String> getMetrics() {
+    return metrics;
+  }
+
+  public List<String> getDatasets() {
+    return datasets;
+  }
+}
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
new file mode 100644
index 0000000..adfa5f9
--- /dev/null
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
@@ -0,0 +1,40 @@
+package org.apache.pinot.thirdeye.dashboard.resources.v2.anomalies;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import java.util.List;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.pinot.thirdeye.api.Constants;
+
+
+@Path(value = "/anomaly-search")
+@Produces(MediaType.APPLICATION_JSON)
+@Api(tags = {Constants.DETECTION_TAG})
+public class AnomalySearchResource {
+
+  private final AnomalySearcher anomalySearcher;
+
+  public AnomalySearchResource() {
+    this.anomalySearcher = new AnomalySearcher();
+  }
+
+  @GET
+  @Produces(MediaType.APPLICATION_JSON)
+  @ApiOperation("Search and paginate anomalies according to the parameters")
+  public Response findAlerts(@QueryParam("limit") @DefaultValue("10") int limit,
+      @QueryParam("offset") @DefaultValue("0") int offset, @QueryParam("startTime") long startTime,
+      @QueryParam("endTime") long endTime, @QueryParam("feedbackStatus") List<String> feedbacks,
+      @QueryParam("subscriptionGroup") List<String> subscriptionGroups,
+      @QueryParam("detectionName") List<String> detectionNames, @QueryParam("metric") List<String> metrics,
+      @QueryParam("dataset") List<String> datasets) {
+    AnomalySearchFilter searchFilter =
+        new AnomalySearchFilter(startTime, endTime, feedbacks, subscriptionGroups, detectionNames, metrics, datasets);
+    return Response.ok().entity(this.anomalySearcher.search(searchFilter, limit, offset)).build();
+  }
+}
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
new file mode 100644
index 0000000..6efad8f
--- /dev/null
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
@@ -0,0 +1,121 @@
+package org.apache.pinot.thirdeye.dashboard.resources.v2.anomalies;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.pinot.thirdeye.constant.AnomalyFeedbackType;
+import org.apache.pinot.thirdeye.datalayer.bao.DetectionAlertConfigManager;
+import org.apache.pinot.thirdeye.datalayer.bao.DetectionConfigManager;
+import org.apache.pinot.thirdeye.datalayer.bao.MergedAnomalyResultManager;
+import org.apache.pinot.thirdeye.datalayer.dto.MergedAnomalyResultDTO;
+import org.apache.pinot.thirdeye.datalayer.pojo.DetectionConfigBean;
+import org.apache.pinot.thirdeye.datalayer.util.Predicate;
+import org.apache.pinot.thirdeye.datasource.DAORegistry;
+
+import static org.apache.pinot.thirdeye.constant.AnomalyFeedbackType.*;
+
+
+public class AnomalySearcher {
+  private final MergedAnomalyResultManager anomalyDAO;
+  private final DetectionConfigManager detectionConfigDAO;
+  private final DetectionAlertConfigManager detectionAlertConfigDAO;
+
+  public AnomalySearcher() {
+    this.anomalyDAO = DAORegistry.getInstance().getMergedAnomalyResultDAO();
+    this.detectionConfigDAO = DAORegistry.getInstance().getDetectionConfigManager();
+    this.detectionAlertConfigDAO = DAORegistry.getInstance().getDetectionAlertConfigManager();
+  }
+
+  /**
+   * Search and retrieve all the anomalies matching to the search filter and limits.
+   *
+   * @param searchFilter the search filter
+   * @param limit the limit
+   * @param offset the offset
+   * @return the result
+   */
+  public Map<String, Object> search(AnomalySearchFilter searchFilter, int limit, int offset) {
+    Predicate predicate = Predicate.AND(Predicate.LT("startTime", searchFilter.getEndTime()),
+        Predicate.GT("endTime", searchFilter.getStartTime()));
+//, Predicate.NEQ("isChild", false)
+    // search by detections or subscription groups
+    Set<Long> detectionConfigIds = new HashSet<>();
+    Set<Long> subscribedDetectionConfigIds = new HashSet<>();
+    if (!searchFilter.getDetectionNames().isEmpty()) {
+      detectionConfigIds =
+          this.detectionConfigDAO.findByPredicate(Predicate.IN("name", searchFilter.getDetectionNames().toArray()))
+              .stream()
+              .map(DetectionConfigBean::getId)
+              .collect(Collectors.toSet());
+    }
+    if (!searchFilter.getSubscriptionGroups().isEmpty()) {
+      subscribedDetectionConfigIds = this.detectionAlertConfigDAO.findByPredicate(
+          Predicate.IN("name", searchFilter.getSubscriptionGroups().toArray()))
+          .stream()
+          .map(detectionAlertConfigDTO -> detectionAlertConfigDTO.getVectorClocks().keySet())
+          .flatMap(Collection::stream)
+          .collect(Collectors.toSet());
+    }
+    if (!searchFilter.getDetectionNames().isEmpty() && !searchFilter.getSubscriptionGroups().isEmpty()) {
+      // intersect the detection config ids if searching by both
+      detectionConfigIds.retainAll(subscribedDetectionConfigIds);
+    } else {
+      detectionConfigIds.addAll(subscribedDetectionConfigIds);
+    }
+    if (!searchFilter.getDetectionNames().isEmpty() || !searchFilter.getSubscriptionGroups().isEmpty()) {
+      // add the predicate using detection config id
+      if (detectionConfigIds.isEmpty()) {
+        // if detection not found, return empty result
+        return ImmutableMap.of("count", 0, "limit", limit, "offset", offset, "elements", Collections.emptyList());
+      }
+      predicate = Predicate.AND(predicate, Predicate.IN("detectionConfigId", detectionConfigIds.toArray()));
+    }
+
+    // search by datasets
+    if (!searchFilter.getDatasets().isEmpty()) {
+      List<Predicate> datasetPredicates = new ArrayList<>();
+      for (String dataset : searchFilter.getDatasets()) {
+        datasetPredicates.add(Predicate.LIKE("collection", "%" + dataset + "%"));
+      }
+      predicate = Predicate.AND(predicate, Predicate.OR(datasetPredicates.toArray(new Predicate[0])));
+    }
+    // search by metrics
+    if (!searchFilter.getMetrics().isEmpty()) {
+      predicate = Predicate.AND(predicate, Predicate.IN("metric", searchFilter.getMetrics().toArray()));
+    }
+
+    long count;
+    List<MergedAnomalyResultDTO> results;
+    if (searchFilter.getFeedbacks().isEmpty()) {
+      List<Long> anomalyIds = this.anomalyDAO.findIdsByPredicate(predicate);
+      count = anomalyIds.size();
+      results = this.anomalyDAO.findByIds(paginateResults(anomalyIds, offset, limit));
+    } else {
+      // filter by feedback types
+      List<MergedAnomalyResultDTO> anomalies = this.anomalyDAO.findByPredicate(predicate);
+      Set<AnomalyFeedbackType> feedbackFilters =
+          searchFilter.getFeedbacks().stream().map(AnomalyFeedbackType::valueOf).collect(Collectors.toSet());
+      results = anomalies.stream()
+          .filter(anomaly -> (anomaly.getFeedback() == null && feedbackFilters.contains(NO_FEEDBACK)) || (
+              anomaly.getFeedback() != null && feedbackFilters.contains(anomaly.getFeedback().getFeedbackType())))
+          .collect(Collectors.toList());
+      count = results.size();
+      results = paginateResults(results, offset, limit);
+    }
+    return ImmutableMap.of("count", count, "limit", limit, "offset", offset, "elements", results);
+  }
+
+  private  <T> List<T> paginateResults(List<T> list, int offset, int limit) {
+    if (offset > list.size()) {
+      // requested page is out of bound
+      return Collections.emptyList();
+    }
+    return list.subList(offset, Math.min(offset + limit, list.size()));
+  }
+}
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java
index 8e3c768..d5941d9 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/entity/MergedAnomalyResultIndex.java
@@ -35,6 +35,7 @@ public class MergedAnomalyResultIndex extends AbstractIndexEntity {
   String metric;
   DimensionMap dimensions;
   boolean notified;
+  boolean isChild;
 
   public long getDetectionConfigId() {
     return detectionConfigId;
@@ -115,4 +116,12 @@ public class MergedAnomalyResultIndex extends AbstractIndexEntity {
   public void setNotified(boolean notified) {
     this.notified = notified;
   }
+
+  public boolean isChild() {
+    return isChild;
+  }
+
+  public void setChild(boolean child) {
+    isChild = child;
+  }
 }
diff --git a/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql b/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql
index c93b922..88c74a1 100644
--- a/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql
+++ b/thirdeye/thirdeye-pinot/src/main/resources/schema/create-schema.sql
@@ -110,6 +110,7 @@ create table if not exists merged_anomaly_result_index (
     base_id bigint(20) not null,
     create_time timestamp,
     update_time timestamp default current_timestamp,
+    is_child boolean,
     version int(10)
 ) ENGINE=InnoDB;
 create index merged_anomaly_result_function_idx on merged_anomaly_result_index(function_id);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org


[incubator-pinot] 03/03: add java docs

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jihao pushed a commit to branch anomalies-pagination
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git

commit b4e073314c403674437d6b6df4f0a4be00d84a64
Author: Jihao Zhang <ji...@linkedin.com>
AuthorDate: Wed Jul 29 16:11:52 2020 -0700

    add java docs
---
 .../v2/anomalies/AnomalySearchFilter.java          | 55 ++++++++++++++++++++++
 .../v2/anomalies/AnomalySearchResource.java        | 21 +++++++++
 .../resources/v2/anomalies/AnomalySearcher.java    | 11 ++++-
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
index fbc17e8..e995e5a 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchFilter.java
@@ -3,6 +3,9 @@ package org.apache.pinot.thirdeye.dashboard.resources.v2.anomalies;
 import java.util.List;
 
 
+/**
+ * The type Anomaly search filter.
+ */
 public class AnomalySearchFilter {
   private final List<String> feedbacks;
   private final List<String> subscriptionGroups;
@@ -13,6 +16,18 @@ public class AnomalySearchFilter {
   private final Long startTime;
   private final Long endTime;
 
+  /**
+   * Instantiates a new Anomaly search filter.
+   *
+   * @param startTime the start time
+   * @param endTime the end time
+   * @param feedbacks the feedbacks
+   * @param subscriptionGroups the subscription groups
+   * @param detectionNames the detection names
+   * @param metrics the metrics
+   * @param datasets the datasets
+   * @param anomalyIds the anomaly ids
+   */
   public AnomalySearchFilter(Long startTime, Long endTime, List<String> feedbacks, List<String> subscriptionGroups, List<String> detectionNames,
       List<String> metrics, List<String> datasets, List<Long> anomalyIds) {
     this.feedbacks = feedbacks;
@@ -25,34 +40,74 @@ public class AnomalySearchFilter {
     this.anomalyIds = anomalyIds;
   }
 
+  /**
+   * Gets start time.
+   *
+   * @return the start time
+   */
   public Long getStartTime() {
     return startTime;
   }
 
+  /**
+   * Gets end time.
+   *
+   * @return the end time
+   */
   public Long getEndTime() {
     return endTime;
   }
 
+  /**
+   * Gets feedbacks.
+   *
+   * @return the feedbacks
+   */
   public List<String> getFeedbacks() {
     return feedbacks;
   }
 
+  /**
+   * Gets subscription groups.
+   *
+   * @return the subscription groups
+   */
   public List<String> getSubscriptionGroups() {
     return subscriptionGroups;
   }
 
+  /**
+   * Gets detection names.
+   *
+   * @return the detection names
+   */
   public List<String> getDetectionNames() {
     return detectionNames;
   }
 
+  /**
+   * Gets metrics.
+   *
+   * @return the metrics
+   */
   public List<String> getMetrics() {
     return metrics;
   }
 
+  /**
+   * Gets datasets.
+   *
+   * @return the datasets
+   */
   public List<String> getDatasets() {
     return datasets;
   }
 
+  /**
+   * Gets anomaly ids.
+   *
+   * @return the anomaly ids
+   */
   public List<Long> getAnomalyIds() {
     return anomalyIds;
   }
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
index 74772a6..81b51a9 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearchResource.java
@@ -13,6 +13,9 @@ import javax.ws.rs.core.Response;
 import org.apache.pinot.thirdeye.api.Constants;
 
 
+/**
+ * The type Anomaly search resource.
+ */
 @Path(value = "/anomaly-search")
 @Produces(MediaType.APPLICATION_JSON)
 @Api(tags = {Constants.DETECTION_TAG})
@@ -20,10 +23,28 @@ public class AnomalySearchResource {
 
   private final AnomalySearcher anomalySearcher;
 
+  /**
+   * Instantiates a new Anomaly search resource.
+   */
   public AnomalySearchResource() {
     this.anomalySearcher = new AnomalySearcher();
   }
 
+  /**
+   * Search and paginate the anomalies according to the parameters.
+   *
+   * @param limit the limit
+   * @param offset the offset
+   * @param startTime the start time
+   * @param endTime the end time
+   * @param feedbacks the feedback types, e.g. ANOMALY, NOT_ANOMALY
+   * @param subscriptionGroups the subscription groups
+   * @param detectionNames the detection names
+   * @param metrics the metrics
+   * @param datasets the datasets
+   * @param anomalyIds the anomaly ids
+   * @return the response
+   */
   @GET
   @Produces(MediaType.APPLICATION_JSON)
   @ApiOperation("Search and paginate anomalies according to the parameters")
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
index bc29228..463cbe3 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/dashboard/resources/v2/anomalies/AnomalySearcher.java
@@ -23,11 +23,17 @@ import org.apache.pinot.thirdeye.datasource.DAORegistry;
 import static org.apache.pinot.thirdeye.constant.AnomalyFeedbackType.*;
 
 
+/**
+ * The type Anomaly searcher.
+ */
 public class AnomalySearcher {
   private final MergedAnomalyResultManager anomalyDAO;
   private final DetectionConfigManager detectionConfigDAO;
   private final DetectionAlertConfigManager detectionAlertConfigDAO;
 
+  /**
+   * Instantiates a new Anomaly searcher.
+   */
   public AnomalySearcher() {
     this.anomalyDAO = DAORegistry.getInstance().getMergedAnomalyResultDAO();
     this.detectionConfigDAO = DAORegistry.getInstance().getDetectionConfigManager();
@@ -108,9 +114,10 @@ public class AnomalySearcher {
           .sorted(Comparator.reverseOrder())
           .collect(Collectors.toList());
       count = anomalyIds.size();
-      results = anomalyIds.isEmpty() ? Collections.emptyList() : this.anomalyDAO.findByIds(paginateResults(anomalyIds, offset, limit));
+      results = anomalyIds.isEmpty() ? Collections.emptyList()
+          : this.anomalyDAO.findByIds(paginateResults(anomalyIds, offset, limit));
     } else {
-      // filter by feedback types
+      // filter by feedback types if requested
       List<MergedAnomalyResultDTO> anomalies = this.anomalyDAO.findByPredicate(predicate);
       Set<AnomalyFeedbackType> feedbackFilters =
           searchFilter.getFeedbacks().stream().map(AnomalyFeedbackType::valueOf).collect(Collectors.toSet());


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org