package com.linkedin.thirdeye.anomalydetection.function;
import com.linkedin.thirdeye.anomaly.views.AnomalyTimelinesView;
import com.linkedin.thirdeye.anomalydetection.context.AnomalyDetectionContext;
import com.linkedin.thirdeye.anomalydetection.context.TimeSeries;
import com.linkedin.thirdeye.anomalydetection.model.data.DataModel;
import com.linkedin.thirdeye.anomalydetection.model.data.NoopDataModel;
import com.linkedin.thirdeye.anomalydetection.model.detection.DetectionModel;
import com.linkedin.thirdeye.anomalydetection.model.detection.MinMaxThresholdDetectionModel;
import com.linkedin.thirdeye.anomalydetection.model.detection.NoopDetectionModel;
import com.linkedin.thirdeye.anomalydetection.model.merge.MergeModel;
import com.linkedin.thirdeye.anomalydetection.model.merge.MinMaxThresholdMergeModel;
import com.linkedin.thirdeye.anomalydetection.model.merge.NoopMergeModel;
import com.linkedin.thirdeye.anomalydetection.model.prediction.ExpectedTimeSeriesPredictionModel;
import com.linkedin.thirdeye.anomalydetection.model.prediction.NoopPredictionModel;
import com.linkedin.thirdeye.anomalydetection.model.prediction.PredictionModel;
import com.linkedin.thirdeye.anomalydetection.model.transform.TransformationFunction;
import com.linkedin.thirdeye.anomalydetection.model.transform.ZeroRemovalFunction;
import com.linkedin.thirdeye.dashboard.views.TimeBucket;
import com.linkedin.thirdeye.datalayer.dto.AnomalyFunctionDTO;
import com.linkedin.thirdeye.datalayer.dto.MergedAnomalyResultDTO;
import java.util.ArrayList;
import java.util.List;
public class MinMaxThresholdFunction extends AbstractModularizedAnomalyFunction {
public static final String MIN_VAL = "min";
public static final String MAX_VAL = "max";
private DataModel dataModel = new NoopDataModel();
private List<TransformationFunction> currentTimeSeriesTransformationChain = new ArrayList<>();
private List<TransformationFunction> baselineTimeSeriesTransformationChain = new ArrayList<>();
private PredictionModel predictionModel = new NoopPredictionModel();
private DetectionModel detectionModel = new NoopDetectionModel();
private MergeModel mergeModel = new NoopMergeModel();
public String[] getPropertyKeys() {
return new String [] {MIN_VAL, MAX_VAL};
}
@Override
public void init(AnomalyFunctionDTO spec) throws Exception {
super.init(spec);
// Removes zeros from time series, which currently mean empty values in ThirdEye.
TransformationFunction zeroRemover = new ZeroRemovalFunction();
currentTimeSeriesTransformationChain.add(zeroRemover);
detectionModel = new MinMaxThresholdDetectionModel();
detectionModel.init(properties);
mergeModel = new MinMaxThresholdMergeModel();
mergeModel.init(properties);
}
@Override
public AnomalyTimelinesView getTimeSeriesView(AnomalyDetectionContext anomalyDetectionContext, long bucketMillis,
String metric, long viewWindowStartTime, long viewWindowEndTime, List<MergedAnomalyResultDTO> knownAnomalies) {
AnomalyTimelinesView anomalyTimelinesView = super
.getTimeSeriesView(anomalyDetectionContext, bucketMillis, metric, viewWindowStartTime, viewWindowEndTime,
knownAnomalies);
// Get min / max props
Double min = null;
if (properties.containsKey(MIN_VAL)) {
min = Double.valueOf(properties.getProperty(MIN_VAL));
}
Double max = null;
if (properties.containsKey(MAX_VAL)) {
max = Double.valueOf(properties.getProperty(MAX_VAL));
}
double value = 0d;
if (min != null) {
value = min;
} else if (max != null) {
value = max;
}
int bucketCount = (int) ((viewWindowEndTime - viewWindowStartTime) / bucketMillis);
for (int i = 0; i < bucketCount; ++i) {
anomalyTimelinesView.addBaselineValues(value);
}
return anomalyTimelinesView;
}
@Override public DataModel getDataModel() {
return dataModel;
}
@Override public List<TransformationFunction> getCurrentTimeSeriesTransformationChain() {
return currentTimeSeriesTransformationChain;
}
@Override public List<TransformationFunction> getBaselineTimeSeriesTransformationChain() {
return baselineTimeSeriesTransformationChain;
}
@Override public PredictionModel getPredictionModel() {
return predictionModel;
}
@Override public DetectionModel getDetectionModel() {
return detectionModel;
}
@Override public MergeModel getMergeModel() {
return mergeModel;
}
}