package com.linkedin.thirdeye.datalayer.pojo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Multimap;
import com.linkedin.thirdeye.anomaly.merge.AnomalyMergeConfig;
import com.linkedin.thirdeye.api.TimeGranularity;
import com.linkedin.thirdeye.constant.MetricAggFunction;
import com.linkedin.thirdeye.util.ThirdEyeUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@JsonIgnoreProperties(ignoreUnknown=true)
public class AnomalyFunctionBean extends AbstractBean {
private String collection;
private String functionName;
// This variable is topic metric, which is used as a search criteria for searching anomalies
private String metric;
// The list of metrics that have to be retrieved in order to detect anomalies for this function
private List<String> metrics;
private MetricAggFunction metricFunction;
private String type;
private boolean isActive = true;
private String globalMetric;
private String properties;
private String cron;
private TimeGranularity frequency = new TimeGranularity(1, TimeUnit.HOURS);
private Integer bucketSize;
private TimeUnit bucketUnit;
private Integer windowSize;
private TimeUnit windowUnit;
private Integer windowDelay;
private TimeUnit windowDelayUnit;
private String exploreDimensions;
private String filters;
private long metricId;
// Used to remove time series with small traffic or total count if the information is available
// This filter is different from the calculation of OTHER dimensions because it removes the time series if the
// count is not satisfied. Moreover, we won't have top level traffic or total count information when this filter
// is invoked, i.e., this filter is a local filter to time series with a certain dimensions.
private Map<String, String> dataFilter;
private Map<String, String> alertFilter;
private AnomalyMergeConfig anomalyMergeConfig;
/**
* This flag always true. The same flag in dataset config, will act as master, always false.
* This flag would typically be unset, in backfill cases, where we want to override the completeness check,
* but not have to touch the dataset config setting for that
*/
private boolean requiresCompletenessCheck = true;
public long getMetricId() {
return metricId;
}
public void setMetricId(long metricId) {
this.metricId = metricId;
}
public String getCollection() {
return collection;
}
public void setCollection(String collection) {
this.collection = collection;
}
public String getFunctionName() {
return functionName;
}
public void setFunctionName(String functionName) {
this.functionName = functionName;
}
public String getMetric() {
return metric;
}
public void setMetric(String metric) {
this.metric = metric;
}
public List<String> getMetrics() {
return metrics;
}
public void setMetrics(List<String> metrics) {
this.metrics = metrics;
}
public MetricAggFunction getMetricFunction() {
return metricFunction;
}
public void setMetricFunction(MetricAggFunction metricFunction) {
this.metricFunction = metricFunction;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean getIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
public String getProperties() {
return properties;
}
public void setProperties(String properties) {
this.properties = properties;
}
public String getCron() {
return cron;
}
public void setCron(String cron) {
this.cron = cron;
}
public String getGlobalMetric() {
return globalMetric;
}
public void setGlobalMetric(String globalMetric) {
this.globalMetric = globalMetric;
}
public TimeGranularity getFrequency() {
return frequency;
}
public void setFrequency(TimeGranularity frequency) {
this.frequency = frequency;
}
public Integer getBucketSize() {
return bucketSize;
}
public void setBucketSize(Integer bucketSize) {
this.bucketSize = bucketSize;
}
public TimeUnit getBucketUnit() {
return bucketUnit;
}
public void setBucketUnit(TimeUnit bucketUnit) {
this.bucketUnit = bucketUnit;
}
public Integer getWindowSize() {
return windowSize;
}
public void setWindowSize(int windowSize) {
this.windowSize = windowSize;
}
public TimeUnit getWindowUnit() {
return windowUnit;
}
public void setWindowUnit(TimeUnit windowUnit) {
this.windowUnit = windowUnit;
}
public Integer getWindowDelay() {
return windowDelay;
}
public void setWindowDelay(int windowDelay) {
this.windowDelay = windowDelay;
}
public TimeUnit getWindowDelayUnit() {
return windowDelayUnit;
}
public void setWindowDelayUnit(TimeUnit windowDelayUnit) {
this.windowDelayUnit = windowDelayUnit;
}
public String getExploreDimensions() {
return exploreDimensions;
}
public void setExploreDimensions(String exploreDimensions) {
this.exploreDimensions = exploreDimensions;
}
public String getFilters() {
return filters;
}
public boolean isRequiresCompletenessCheck() {
return requiresCompletenessCheck;
}
public void setRequiresCompletenessCheck(boolean requiresCompletenessCheck) {
this.requiresCompletenessCheck = requiresCompletenessCheck;
}
@JsonIgnore
@JsonProperty("wrapper")
public Multimap<String, String> getFilterSet() {
return ThirdEyeUtils.getFilterSet(filters);
}
@JsonIgnore
@JsonProperty("wrapper")
public void setFilters(String filters) {
String sortedFilters = ThirdEyeUtils.getSortedFilters(filters);
this.filters = sortedFilters;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public Map<String, String> getAlertFilter() {
return alertFilter;
}
public void setAlertFilter(Map<String, String> alertFilter) {
this.alertFilter = alertFilter;
}
public Map<String, String> getDataFilter() {
return dataFilter;
}
public void setDataFilter(Map<String, String> dataFilter) {
this.dataFilter = dataFilter;
}
public AnomalyMergeConfig getAnomalyMergeConfig() {
return anomalyMergeConfig;
}
public void setAnomalyMergeConfig(AnomalyMergeConfig anomalyMergeConfig) {
this.anomalyMergeConfig = anomalyMergeConfig;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof AnomalyFunctionBean)) {
return false;
}
AnomalyFunctionBean af = (AnomalyFunctionBean) o;
return Objects.equals(getId(), af.getId()) && Objects.equals(collection, af.getCollection())
&& Objects.equals(metric, af.getMetric())
&& Objects.equals(metrics, af.getMetrics())
&& Objects.equals(metricFunction, af.getMetricFunction())
&& Objects.equals(type, af.getType()) && Objects.equals(isActive, af.getIsActive())
&& Objects.equals(cron, af.getCron()) && Objects.equals(properties, af.getProperties())
&& Objects.equals(frequency, af.getFrequency())
&& Objects.equals(bucketSize, af.getBucketSize())
&& Objects.equals(bucketUnit, af.getBucketUnit())
&& Objects.equals(windowSize, af.getWindowSize())
&& Objects.equals(windowUnit, af.getWindowUnit())
&& Objects.equals(windowDelay, af.getWindowDelay())
&& Objects.equals(windowDelayUnit, af.getWindowDelayUnit())
&& Objects.equals(exploreDimensions, af.getExploreDimensions())
&& Objects.equals(filters, af.getFilters())
&& Objects.equals(globalMetric, af.getGlobalMetric())
&& Objects.equals(alertFilter, af.getAlertFilter())
&& Objects.equals(requiresCompletenessCheck, af.isRequiresCompletenessCheck());
}
@Override
public int hashCode() {
return Objects.hash(getId(), collection, metric, metrics, metricFunction, type, isActive, cron, frequency,
properties, bucketSize, bucketUnit, windowSize, windowUnit, windowDelay, windowDelayUnit,
exploreDimensions, filters, globalMetric, alertFilter, requiresCompletenessCheck);
}
}