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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8cadaec  [TE] Anomaly detection for monthly data (#3949)
8cadaec is described below

commit 8cadaecfbc3407358c60d7e4d25106e4d3562c3a
Author: Jihao Zhang <[email protected]>
AuthorDate: Mon Mar 11 15:37:08 2019 -0700

    [TE] Anomaly detection for monthly data (#3949)
---
 .../pinot/thirdeye/detection/DetectionUtils.java   | 23 ++++++++--
 .../components/AbsoluteChangeRuleDetector.java     | 18 +++++++-
 .../components/PercentageChangeRuleDetector.java   | 49 ++++++++++++++--------
 .../components/ThresholdRuleDetector.java          | 20 +++++++--
 .../spec/AbsoluteChangeRuleDetectorSpec.java       | 12 ++++++
 .../spec/PercentageChangeRuleDetectorSpec.java     | 12 ++++++
 .../detection/spec/ThresholdRuleDetectorSpec.java  | 10 +++++
 .../PercentageChangeRuleDetectorTest.java          | 21 ++++++++++
 .../components/ThresholdRuleDetectorTest.java      | 28 +++++++++++++
 9 files changed, 166 insertions(+), 27 deletions(-)

diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionUtils.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionUtils.java
index ddae32b..50e4a98 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionUtils.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionUtils.java
@@ -27,6 +27,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.apache.pinot.thirdeye.common.dimension.DimensionMap;
+import org.apache.pinot.thirdeye.common.time.TimeGranularity;
 import org.apache.pinot.thirdeye.dataframe.BooleanSeries;
 import org.apache.pinot.thirdeye.dataframe.DataFrame;
 import org.apache.pinot.thirdeye.dataframe.LongSeries;
@@ -42,6 +43,7 @@ import 
org.apache.pinot.thirdeye.detection.spi.model.TimeSeries;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.Period;
+import org.joda.time.PeriodType;
 
 import static org.apache.pinot.thirdeye.dataframe.util.DataFrameUtils.*;
 
@@ -84,10 +86,11 @@ public class DetectionUtils {
    * @param df time series with COL_TIME and at least one boolean value series
    * @param seriesName name of the value series
    * @param endTime end time of this detection window
+   * @param monitoringGranularityPeriod the monitoring granularity period
    * @param dataset dataset config for the metric
    * @return list of anomalies
    */
-  public static List<MergedAnomalyResultDTO> makeAnomalies(MetricSlice slice, 
DataFrame df, String seriesName, long endTime, DatasetConfigDTO dataset) {
+  public static List<MergedAnomalyResultDTO> makeAnomalies(MetricSlice slice, 
DataFrame df, String seriesName, long endTime, Period 
monitoringGranularityPeriod, DatasetConfigDTO dataset) {
     if (df.isEmpty()) {
       return Collections.emptyList();
     }
@@ -128,12 +131,11 @@ public class DetectionUtils {
 
       // guess-timate of next time series timestamp
       if (dataset != null) {
-        Period period = dataset.bucketTimeGranularity().toPeriod();
         DateTimeZone timezone = DateTimeZone.forID(dataset.getTimezone());
 
         long lastTimestamp = sTime.getLong(sTime.size() - 1);
 
-        end = new DateTime(lastTimestamp, timezone).plus(period).getMillis();
+        end = new DateTime(lastTimestamp, 
timezone).plus(monitoringGranularityPeriod).getMillis();
       }
 
       // truncate at analysis end time
@@ -202,4 +204,19 @@ public class DetectionUtils {
     }
     return 
baselineProvider.computePredictedTimeSeries(MetricSlice.from(metricId, start, 
end, filters));
   }
+
+  /**
+   * Get the joda period for a monitoring granularity
+   * @param monitoringGranularity
+   */
+  public static Period getMonitoringGranularityPeriod(String 
monitoringGranularity, DatasetConfigDTO datasetConfigDTO) {
+    if 
(monitoringGranularity.equals(MetricSlice.NATIVE_GRANULARITY.toAggregationGranularityString()))
 {
+      return datasetConfigDTO.bucketTimeGranularity().toPeriod();
+    }
+    if (monitoringGranularity.equals("1_MONTHS")) {
+      return new Period(0,1,0,0,0,0,0,0, PeriodType.months());
+    }
+    return TimeGranularity.fromString(monitoringGranularity).toPeriod();
+  }
+
 }
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/AbsoluteChangeRuleDetector.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/AbsoluteChangeRuleDetector.java
index d2946f4..a5a2ab9 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/AbsoluteChangeRuleDetector.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/AbsoluteChangeRuleDetector.java
@@ -19,6 +19,7 @@
 
 package org.apache.pinot.thirdeye.detection.components;
 
+import org.apache.pinot.thirdeye.common.time.TimeGranularity;
 import org.apache.pinot.thirdeye.dashboard.resources.v2.BaselineParsingUtils;
 import org.apache.pinot.thirdeye.dataframe.BooleanSeries;
 import org.apache.pinot.thirdeye.dataframe.DataFrame;
@@ -42,6 +43,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import org.joda.time.Interval;
+import org.joda.time.Period;
 
 import static org.apache.pinot.thirdeye.dataframe.util.DataFrameUtils.*;
 
@@ -62,6 +64,9 @@ public class AbsoluteChangeRuleDetector implements 
AnomalyDetector<AbsoluteChang
   private InputDataFetcher dataFetcher;
   private Baseline baseline;
   private Pattern pattern;
+  private String monitoringGranularity;
+  private TimeGranularity timeGranularity;
+
   private static final String COL_CURR = "current";
   private static final String COL_BASE = "baseline";
   private static final String COL_ANOMALY = "anomaly";
@@ -72,7 +77,7 @@ public class AbsoluteChangeRuleDetector implements 
AnomalyDetector<AbsoluteChang
   @Override
   public List<MergedAnomalyResultDTO> runDetection(Interval window, String 
metricUrn) {
     MetricEntity me = MetricEntity.fromURN(metricUrn);
-    MetricSlice slice = MetricSlice.from(me.getId(), window.getStartMillis(), 
window.getEndMillis(), me.getFilters());
+    MetricSlice slice = MetricSlice.from(me.getId(), window.getStartMillis(), 
window.getEndMillis(), me.getFilters(), timeGranularity);
     List<MetricSlice> slices = new ArrayList<>(this.baseline.scatter(slice));
     slices.add(slice);
     InputData data = this.dataFetcher.fetchData(new 
InputDataSpec().withTimeseriesSlices(slices).withMetricIdsForDataset(
@@ -100,7 +105,8 @@ public class AbsoluteChangeRuleDetector implements 
AnomalyDetector<AbsoluteChang
 
     // make anomalies
     DatasetConfigDTO datasetConfig = 
data.getDatasetForMetricId().get(me.getId());
-    return DetectionUtils.makeAnomalies(slice, df, COL_ANOMALY, 
window.getEndMillis(), datasetConfig);
+    return DetectionUtils.makeAnomalies(slice, df, COL_ANOMALY, 
window.getEndMillis(),
+        DetectionUtils.getMonitoringGranularityPeriod(monitoringGranularity, 
datasetConfig), datasetConfig);
   }
 
   @Override
@@ -111,5 +117,13 @@ public class AbsoluteChangeRuleDetector implements 
AnomalyDetector<AbsoluteChang
     String offset = spec.getOffset();
     this.baseline = BaselineParsingUtils.parseOffset(offset, timezone);
     this.pattern = Pattern.valueOf(spec.getPattern().toUpperCase());
+
+    this.monitoringGranularity = spec.getMonitoringGranularity();
+    if (this.monitoringGranularity.equals("1_MONTHS")) {
+      this.timeGranularity = MetricSlice.NATIVE_GRANULARITY;
+    } else {
+      this.timeGranularity = 
TimeGranularity.fromString(spec.getMonitoringGranularity());
+    }
+
   }
 }
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetector.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetector.java
index e84220b..5d717fb 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetector.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetector.java
@@ -19,6 +19,7 @@
 
 package org.apache.pinot.thirdeye.detection.components;
 
+import org.apache.pinot.thirdeye.common.time.TimeGranularity;
 import org.apache.pinot.thirdeye.dashboard.resources.v2.BaselineParsingUtils;
 import org.apache.pinot.thirdeye.dataframe.BooleanSeries;
 import org.apache.pinot.thirdeye.dataframe.DataFrame;
@@ -43,28 +44,28 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import org.joda.time.Interval;
+import org.joda.time.Period;
+import org.joda.time.PeriodType;
 
 import static org.apache.pinot.thirdeye.dataframe.DoubleSeries.*;
 import static org.apache.pinot.thirdeye.dataframe.util.DataFrameUtils.*;
 
-@Components(title = "Percentage change rule detection",
-    type = "PERCENTAGE_RULE",
-    tags = {DetectionTag.RULE_DETECTION},
-    description = "Computes a multi-week aggregate baseline and compares the 
current value "
-        + "based on relative change.",
-    presentation = {
-        @PresentationOption(name = "percentage change", template = "comparing 
${offset} is ${pattern} more than ${percentageChange}")
-    },
-    params = {
-        @Param(name = "offset", defaultValue = "wo1w"),
-        @Param(name = "percentageChange", placeholder = "value"),
-        @Param(name = "pattern", allowableValues = {"up", "down"})
-    })
+
+@Components(title = "Percentage change rule detection", type = 
"PERCENTAGE_RULE", tags = {
+    DetectionTag.RULE_DETECTION}, description =
+    "Computes a multi-week aggregate baseline and compares the current value "
+        + "based on relative change.", presentation = {
+    @PresentationOption(name = "percentage change", template = "comparing 
${offset} is ${pattern} more than ${percentageChange}")}, params = {
+    @Param(name = "offset", defaultValue = "wo1w"), @Param(name = 
"percentageChange", placeholder = "value"),
+    @Param(name = "pattern", allowableValues = {"up", "down"})})
 public class PercentageChangeRuleDetector implements 
AnomalyDetector<PercentageChangeRuleDetectorSpec> {
   private double percentageChange;
   private InputDataFetcher dataFetcher;
   private Baseline baseline;
   private Pattern pattern;
+  private String monitoringGranularity;
+  private TimeGranularity timeGranularity;
+
   private static final String COL_CURR = "current";
   private static final String COL_BASE = "baseline";
   private static final String COL_CHANGE = "change";
@@ -75,10 +76,13 @@ public class PercentageChangeRuleDetector implements 
AnomalyDetector<PercentageC
   @Override
   public List<MergedAnomalyResultDTO> runDetection(Interval window, String 
metricUrn) {
     MetricEntity me = MetricEntity.fromURN(metricUrn);
-    MetricSlice slice = MetricSlice.from(me.getId(), window.getStartMillis(), 
window.getEndMillis(), me.getFilters());
+    MetricSlice slice =
+        MetricSlice.from(me.getId(), window.getStartMillis(), 
window.getEndMillis(), me.getFilters(), timeGranularity);
     List<MetricSlice> slices = new ArrayList<>(this.baseline.scatter(slice));
     slices.add(slice);
-    InputData data = this.dataFetcher.fetchData(new 
InputDataSpec().withTimeseriesSlices(slices).withMetricIdsForDataset(Collections.singletonList(slice.getMetricId())));
+
+    InputData data = this.dataFetcher.fetchData(new 
InputDataSpec().withTimeseriesSlices(slices)
+        
.withMetricIdsForDataset(Collections.singletonList(slice.getMetricId())));
     DataFrame dfCurr = data.getTimeseries().get(slice).renameSeries(COL_VALUE, 
COL_CURR);
     DataFrame dfBase = this.baseline.gather(slice, 
data.getTimeseries()).renameSeries(COL_VALUE, COL_BASE);
 
@@ -98,10 +102,11 @@ public class PercentageChangeRuleDetector implements 
AnomalyDetector<PercentageC
     // relative change
     if (!Double.isNaN(this.percentageChange)) {
       // consistent with pattern
-      if (pattern.equals(Pattern.UP_OR_DOWN) ) {
+      if (pattern.equals(Pattern.UP_OR_DOWN)) {
         df.addSeries(COL_PATTERN, BooleanSeries.fillValues(df.size(), true));
       } else {
-        df.addSeries(COL_PATTERN, this.pattern.equals(Pattern.UP) ? 
df.getDoubles(COL_CHANGE).gt(0) : df.getDoubles(COL_CHANGE).lt(0));
+        df.addSeries(COL_PATTERN,
+            this.pattern.equals(Pattern.UP) ? df.getDoubles(COL_CHANGE).gt(0) 
: df.getDoubles(COL_CHANGE).lt(0));
       }
       df.addSeries(COL_CHANGE_VIOLATION, 
df.getDoubles(COL_CHANGE).abs().gte(this.percentageChange));
       df.mapInPlace(BooleanSeries.ALL_TRUE, COL_ANOMALY, COL_PATTERN, 
COL_CHANGE_VIOLATION);
@@ -109,7 +114,8 @@ public class PercentageChangeRuleDetector implements 
AnomalyDetector<PercentageC
 
     // anomalies
     DatasetConfigDTO datasetConfig = 
data.getDatasetForMetricId().get(me.getId());
-    return DetectionUtils.makeAnomalies(slice, df, COL_ANOMALY, 
window.getEndMillis(), datasetConfig);
+    return DetectionUtils.makeAnomalies(slice, df, COL_ANOMALY, 
window.getEndMillis(),
+        DetectionUtils.getMonitoringGranularityPeriod(monitoringGranularity, 
datasetConfig), datasetConfig);
   }
 
   @Override
@@ -120,5 +126,12 @@ public class PercentageChangeRuleDetector implements 
AnomalyDetector<PercentageC
     String offset = spec.getOffset();
     this.baseline = BaselineParsingUtils.parseOffset(offset, timezone);
     this.pattern = Pattern.valueOf(spec.getPattern().toUpperCase());
+
+    this.monitoringGranularity = spec.getMonitoringGranularity();
+    if (this.monitoringGranularity.equals("1_MONTHS")) {
+      this.timeGranularity = MetricSlice.NATIVE_GRANULARITY;
+    } else {
+      this.timeGranularity = 
TimeGranularity.fromString(spec.getMonitoringGranularity());
+    }
   }
 }
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetector.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetector.java
index 63a5604..236e457 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetector.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetector.java
@@ -19,6 +19,9 @@
 
 package org.apache.pinot.thirdeye.detection.components;
 
+import java.util.Collections;
+import java.util.List;
+import org.apache.pinot.thirdeye.common.time.TimeGranularity;
 import org.apache.pinot.thirdeye.dataframe.BooleanSeries;
 import org.apache.pinot.thirdeye.dataframe.DataFrame;
 import org.apache.pinot.thirdeye.dataframe.util.MetricSlice;
@@ -35,9 +38,8 @@ import 
org.apache.pinot.thirdeye.detection.spi.components.AnomalyDetector;
 import org.apache.pinot.thirdeye.detection.spi.model.InputData;
 import org.apache.pinot.thirdeye.detection.spi.model.InputDataSpec;
 import org.apache.pinot.thirdeye.rootcause.impl.MetricEntity;
-import java.util.Collections;
-import java.util.List;
 import org.joda.time.Interval;
+import org.joda.time.Period;
 
 import static org.apache.pinot.thirdeye.dataframe.util.DataFrameUtils.*;
 
@@ -54,12 +56,14 @@ public class ThresholdRuleDetector implements 
AnomalyDetector<ThresholdRuleDetec
   private double min;
   private double max;
   private InputDataFetcher dataFetcher;
+  private String monitoringGranularity;
+  private TimeGranularity timeGranularity;
 
   @Override
   public List<MergedAnomalyResultDTO> runDetection(Interval window, String 
metricUrn) {
     MetricEntity me = MetricEntity.fromURN(metricUrn);
     Long endTime = window.getEndMillis();
-    MetricSlice slice = MetricSlice.from(me.getId(), window.getStartMillis(), 
endTime, me.getFilters());
+    MetricSlice slice = MetricSlice.from(me.getId(), window.getStartMillis(), 
endTime, me.getFilters(), timeGranularity);
 
     InputData data = this.dataFetcher.fetchData(
         new 
InputDataSpec().withTimeseriesSlices(Collections.singletonList(slice))
@@ -83,7 +87,8 @@ public class ThresholdRuleDetector implements 
AnomalyDetector<ThresholdRuleDetec
     df.mapInPlace(BooleanSeries.HAS_TRUE, COL_ANOMALY, COL_TOO_HIGH, 
COL_TOO_LOW);
 
     DatasetConfigDTO datasetConfig = 
data.getDatasetForMetricId().get(me.getId());
-    return DetectionUtils.makeAnomalies(slice, df, COL_ANOMALY, endTime, 
datasetConfig);
+    return DetectionUtils.makeAnomalies(slice, df, COL_ANOMALY, endTime,
+        DetectionUtils.getMonitoringGranularityPeriod(monitoringGranularity, 
datasetConfig), datasetConfig);
   }
 
   @Override
@@ -91,5 +96,12 @@ public class ThresholdRuleDetector implements 
AnomalyDetector<ThresholdRuleDetec
     this.min = spec.getMin();
     this.max = spec.getMax();
     this.dataFetcher = dataFetcher;
+    this.monitoringGranularity = spec.getMonitoringGranularity();
+    if (this.monitoringGranularity.equals("1_MONTHS")) {
+      this.timeGranularity = MetricSlice.NATIVE_GRANULARITY;
+    } else {
+      this.timeGranularity = 
TimeGranularity.fromString(spec.getMonitoringGranularity());
+    }
+
   }
 }
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/AbsoluteChangeRuleDetectorSpec.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/AbsoluteChangeRuleDetectorSpec.java
index 3d02492..601d36d 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/AbsoluteChangeRuleDetectorSpec.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/AbsoluteChangeRuleDetectorSpec.java
@@ -19,11 +19,23 @@
 
 package org.apache.pinot.thirdeye.detection.spec;
 
+import org.apache.pinot.thirdeye.dataframe.util.MetricSlice;
+
+
 public class AbsoluteChangeRuleDetectorSpec extends AbstractSpec {
   private double absoluteChange = Double.NaN;
   private String offset = "wo1w";
   private String timezone = "UTC";
   private String pattern = "UP_OR_DOWN";
+  private String monitoringGranularity = 
MetricSlice.NATIVE_GRANULARITY.toAggregationGranularityString(); // use native 
granularity by default
+
+  public String getMonitoringGranularity() {
+    return monitoringGranularity;
+  }
+
+  public void setMonitoringGranularity(String monitoringGranularity) {
+    this.monitoringGranularity = monitoringGranularity;
+  }
 
   public double getAbsoluteChange() {
     return absoluteChange;
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/PercentageChangeRuleDetectorSpec.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/PercentageChangeRuleDetectorSpec.java
index 25a9079..694699d 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/PercentageChangeRuleDetectorSpec.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/PercentageChangeRuleDetectorSpec.java
@@ -19,11 +19,23 @@
 
 package org.apache.pinot.thirdeye.detection.spec;
 
+import org.apache.pinot.thirdeye.dataframe.util.MetricSlice;
+
+
 public class PercentageChangeRuleDetectorSpec extends AbstractSpec {
   private double percentageChange = Double.NaN;
   private String offset = "wo1w";
   private String timezone = "UTC";
   private String pattern = "UP_OR_DOWN";
+  private String monitoringGranularity = 
MetricSlice.NATIVE_GRANULARITY.toAggregationGranularityString(); // use native 
granularity by default
+
+  public String getMonitoringGranularity() {
+    return monitoringGranularity;
+  }
+
+  public void setMonitoringGranularity(String monitoringGranularity) {
+    this.monitoringGranularity = monitoringGranularity;
+  }
 
   public String getPattern() {
     return pattern;
diff --git 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/ThresholdRuleDetectorSpec.java
 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/ThresholdRuleDetectorSpec.java
index 11b4561..7e706aa 100644
--- 
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/ThresholdRuleDetectorSpec.java
+++ 
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/spec/ThresholdRuleDetectorSpec.java
@@ -20,12 +20,22 @@
 package org.apache.pinot.thirdeye.detection.spec;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.apache.pinot.thirdeye.dataframe.util.MetricSlice;
 
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class ThresholdRuleDetectorSpec extends AbstractSpec {
   private double min = Double.NaN;
   private double max = Double.NaN;
+  private String monitoringGranularity = 
MetricSlice.NATIVE_GRANULARITY.toAggregationGranularityString(); // use native 
granularity by default
+
+  public String getMonitoringGranularity() {
+    return monitoringGranularity;
+  }
+
+  public void setMonitoringGranularity(String monitoringGranularity) {
+    this.monitoringGranularity = monitoringGranularity;
+  }
 
   public double getMin() {
     return min;
diff --git 
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetectorTest.java
 
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetectorTest.java
index 7218d08..f52bd23 100644
--- 
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetectorTest.java
+++ 
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/PercentageChangeRuleDetectorTest.java
@@ -34,6 +34,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import org.apache.pinot.thirdeye.detection.spec.ThresholdRuleDetectorSpec;
+import org.apache.pinot.thirdeye.detection.spi.components.AnomalyDetector;
 import org.joda.time.Interval;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
@@ -70,6 +72,11 @@ public class PercentageChangeRuleDetectorTest {
     timeseries.put(MetricSlice.from(1L, 604800000L, 1209600000L), this.data);
     timeseries.put(MetricSlice.from(1L, 1209600000L, 1814400000L), this.data);
     timeseries.put(MetricSlice.from(1L, 1814400000L, 2419200000L), this.data);
+    timeseries.put(MetricSlice.from(1L, 1546214400000L, 1551312000000L),
+        new DataFrame().addSeries(COL_TIME, 1546214400000L, 
1548892800000L).addSeries(COL_VALUE, 100, 200));
+    timeseries.put(MetricSlice.from(1L, 1543536000000L, 1548633600000L),
+        new DataFrame().addSeries(COL_TIME, 1543536000000L, 1546214400000L)
+            .addSeries(COL_VALUE, 100, 100));
 
     this.provider = new MockDataProvider()
         .setTimeseries(timeseries)
@@ -148,4 +155,18 @@ public class PercentageChangeRuleDetectorTest {
     Assert.assertEquals(anomalies.get(4).getEndTime(), 2325600000L);
   }
 
+  @Test
+  public void testMonthlyDetectionPercentage() {
+    AnomalyDetector percentageRule = new PercentageChangeRuleDetector();
+    PercentageChangeRuleDetectorSpec spec = new 
PercentageChangeRuleDetectorSpec();
+    spec.setOffset("mo1m");
+    spec.setPercentageChange(0.4);
+    spec.setMonitoringGranularity("1_MONTHS");
+    percentageRule.init(spec, new DefaultInputDataFetcher(this.provider, -1));
+    List<MergedAnomalyResultDTO> anomalies = percentageRule.runDetection(new 
Interval(1546214400000L, 1551312000000L), "thirdeye:metric:1");
+    Assert.assertEquals(anomalies.size(), 1);
+    Assert.assertEquals(anomalies.get(0).getStartTime(), 1548892800000L);
+    Assert.assertEquals(anomalies.get(0).getEndTime(), 1551312000000L);
+  }
+
 }
\ No newline at end of file
diff --git 
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetectorTest.java
 
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetectorTest.java
index 1b1a267..51c2ad6 100644
--- 
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetectorTest.java
+++ 
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/components/ThresholdRuleDetectorTest.java
@@ -48,6 +48,8 @@ public class ThresholdRuleDetectorTest {
     Map<MetricSlice, DataFrame> timeSeries = new HashMap<>();
     timeSeries.put(MetricSlice.from(123L, 0, 10),
         new DataFrame().addSeries(COL_VALUE, 0, 100, 200, 500, 
1000).addSeries(COL_TIME, 0, 2, 4, 6, 8));
+    timeSeries.put(MetricSlice.from(123L, 1546214400000L, 1551398400000L),
+        new DataFrame().addSeries(COL_TIME, 1546214400000L, 1548892800000L, 
1551312000000L).addSeries(COL_VALUE, 100, 200, 300));
 
     MetricConfigDTO metricConfigDTO = new MetricConfigDTO();
     metricConfigDTO.setId(123L);
@@ -94,4 +96,30 @@ public class ThresholdRuleDetectorTest {
     Assert.assertEquals(anomalies.get(1).getEndTime(), 10);
   }
 
+  @Test
+  public void testMonthlyDetectionThreshold() {
+    AnomalyDetector thresholdRule = new ThresholdRuleDetector();
+    ThresholdRuleDetectorSpec spec = new ThresholdRuleDetectorSpec();
+    spec.setMin(200);
+    spec.setMonitoringGranularity("1_MONTHS");
+    thresholdRule.init(spec, new DefaultInputDataFetcher(testDataProvider, 
-1));
+    List<MergedAnomalyResultDTO> anomalies = thresholdRule.runDetection(new 
Interval(1546214400000L, 1551398400000L), "thirdeye:metric:123");
+    Assert.assertEquals(anomalies.size(), 1);
+    Assert.assertEquals(anomalies.get(0).getStartTime(), 1546214400000L);
+    Assert.assertEquals(anomalies.get(0).getEndTime(), 1548892800000L);
+  }
+
+  @Test
+  public void testMonthlyDetectionThresholdMax() {
+    AnomalyDetector thresholdRule = new ThresholdRuleDetector();
+    ThresholdRuleDetectorSpec spec = new ThresholdRuleDetectorSpec();
+    spec.setMax(200);
+    spec.setMonitoringGranularity("1_MONTHS");
+    thresholdRule.init(spec, new DefaultInputDataFetcher(testDataProvider, 
-1));
+    List<MergedAnomalyResultDTO> anomalies = thresholdRule.runDetection(new 
Interval(1546214400000L, 1551398400000L), "thirdeye:metric:123");
+    Assert.assertEquals(anomalies.size(), 1);
+    Assert.assertEquals(anomalies.get(0).getStartTime(), 1551312000000L);
+    Assert.assertEquals(anomalies.get(0).getEndTime(), 1551398400000L);
+  }
+
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to