use of com.linkedin.thirdeye.api.TimeGranularity in project pinot by linkedin.
the class PqlUtils method getBetweenClause.
static String getBetweenClause(DateTime start, DateTime endExclusive, TimeSpec timeFieldSpec, String collection) throws ExecutionException {
TimeGranularity dataGranularity = timeFieldSpec.getDataGranularity();
long startMillis = start.getMillis();
long endMillis = endExclusive.getMillis();
long dataGranularityMillis = dataGranularity.toMillis();
String timeField = timeFieldSpec.getColumnName();
String timeFormat = timeFieldSpec.getFormat();
if (timeFormat == null || TimeSpec.SINCE_EPOCH_FORMAT.equals(timeFormat)) {
// Shrink start and end as per data granularity
long startAlignmentDelta = startMillis % dataGranularityMillis;
if (startAlignmentDelta != 0) {
long startMillisAligned = startMillis + dataGranularityMillis - startAlignmentDelta;
start = new DateTime(startMillisAligned);
}
long endAligmentDelta = endMillis % dataGranularityMillis;
if (endAligmentDelta != 0) {
long endMillisAligned = endMillis - endAligmentDelta;
endExclusive = new DateTime(endMillisAligned);
}
}
String startQueryTime;
String endQueryTimeExclusive;
if (timeFormat == null || TimeSpec.SINCE_EPOCH_FORMAT.equals(timeFormat)) {
long startInConvertedUnits = dataGranularity.convertToUnit(start.getMillis());
long endInConvertedUnits = dataGranularity.convertToUnit(endExclusive.getMillis());
startQueryTime = String.valueOf(startInConvertedUnits);
endQueryTimeExclusive = (endInConvertedUnits == startInConvertedUnits + 1) ? startQueryTime : String.valueOf(endInConvertedUnits);
} else {
DateTimeFormatter inputDataDateTimeFormatter = DateTimeFormat.forPattern(timeFormat).withZone(Utils.getDataTimeZone(collection));
startQueryTime = inputDataDateTimeFormatter.print(start);
endQueryTimeExclusive = inputDataDateTimeFormatter.print(endExclusive);
}
if (startQueryTime.equals(endQueryTimeExclusive)) {
return String.format(" %s = %s", timeField, startQueryTime);
} else {
return String.format(" %s >= %s AND %s < %s", timeField, startQueryTime, timeField, endQueryTimeExclusive);
}
}
use of com.linkedin.thirdeye.api.TimeGranularity in project pinot by linkedin.
the class AnomalyResource method getAnomalyMergedResultTimeSeries.
/**
* Returns the time series for the given anomaly.
*
* If viewWindowStartTime and/or viewWindowEndTime is not given, then a window is padded automatically. The padded
* windows is half of the anomaly window size. For instance, if the anomaly lasts for 4 hours, then the pad window
* size is 2 hours. The max padding size is 1 day.
*
* @param anomalyResultId the id of the given anomaly
* @param viewWindowStartTime start time of the time series, inclusive
* @param viewWindowEndTime end time of the time series, inclusive
* @return the time series of the given anomaly
* @throws Exception when it fails to retrieve collection, i.e., dataset, information
*/
@GET
@Path("/anomaly-merged-result/timeseries/{anomaly_merged_result_id}")
public AnomalyTimelinesView getAnomalyMergedResultTimeSeries(@NotNull @PathParam("anomaly_merged_result_id") long anomalyResultId, @NotNull @QueryParam("aggTimeGranularity") String aggTimeGranularity, @QueryParam("start") long viewWindowStartTime, @QueryParam("end") long viewWindowEndTime) throws Exception {
boolean loadRawAnomalies = false;
MergedAnomalyResultDTO anomalyResult = anomalyMergedResultDAO.findById(anomalyResultId, loadRawAnomalies);
DimensionMap dimensions = anomalyResult.getDimensions();
AnomalyFunctionDTO anomalyFunctionSpec = anomalyResult.getFunction();
BaseAnomalyFunction anomalyFunction = anomalyFunctionFactory.fromSpec(anomalyFunctionSpec);
// By default, the padding window size is half of the anomaly window.
if (viewWindowStartTime == 0 || viewWindowEndTime == 0) {
long anomalyWindowStartTime = anomalyResult.getStartTime();
long anomalyWindowEndTime = anomalyResult.getEndTime();
long bucketMillis = TimeUnit.MILLISECONDS.convert(anomalyFunctionSpec.getBucketSize(), anomalyFunctionSpec.getBucketUnit());
long bucketCount = (anomalyWindowEndTime - anomalyWindowStartTime) / bucketMillis;
long paddingMillis = Math.max(1, (bucketCount / 2)) * bucketMillis;
if (paddingMillis > TimeUnit.DAYS.toMillis(1)) {
paddingMillis = TimeUnit.DAYS.toMillis(1);
}
if (viewWindowStartTime == 0) {
viewWindowStartTime = anomalyWindowStartTime - paddingMillis;
}
if (viewWindowEndTime == 0) {
viewWindowEndTime = anomalyWindowEndTime + paddingMillis;
}
}
TimeGranularity timeGranularity = Utils.getAggregationTimeGranularity(aggTimeGranularity, anomalyFunctionSpec.getCollection());
long bucketMillis = timeGranularity.toMillis();
// ThirdEye backend is end time exclusive, so one more bucket is appended to make end time inclusive for frontend.
viewWindowEndTime += bucketMillis;
long maxDataTime = collectionMaxDataTimeCache.get(anomalyResult.getCollection());
if (viewWindowEndTime > maxDataTime) {
viewWindowEndTime = (anomalyResult.getEndTime() > maxDataTime) ? anomalyResult.getEndTime() : maxDataTime;
}
AnomalyDetectionInputContext adInputContext = TimeBasedAnomalyMerger.fetchDataByDimension(viewWindowStartTime, viewWindowEndTime, dimensions, anomalyFunction, anomalyMergedResultDAO, overrideConfigDAO, false);
MetricTimeSeries metricTimeSeries = adInputContext.getDimensionKeyMetricTimeSeriesMap().get(dimensions);
if (metricTimeSeries == null) {
// the timeseries for the given anomaly
return new AnomalyTimelinesView();
}
// Transform time series with scaling factor
List<ScalingFactor> scalingFactors = adInputContext.getScalingFactors();
if (CollectionUtils.isNotEmpty(scalingFactors)) {
Properties properties = anomalyFunction.getProperties();
MetricTransfer.rescaleMetric(metricTimeSeries, viewWindowStartTime, scalingFactors, anomalyFunctionSpec.getTopicMetric(), properties);
}
List<MergedAnomalyResultDTO> knownAnomalies = adInputContext.getKnownMergedAnomalies().get(dimensions);
// Known anomalies are ignored (the null parameter) because 1. we can reduce users' waiting time and 2. presentation
// data does not need to be as accurate as the one used for detecting anomalies
AnomalyTimelinesView anomalyTimelinesView = anomalyFunction.getTimeSeriesView(metricTimeSeries, bucketMillis, anomalyFunctionSpec.getTopicMetric(), viewWindowStartTime, viewWindowEndTime, knownAnomalies);
// Generate summary for frontend
List<TimeBucket> timeBuckets = anomalyTimelinesView.getTimeBuckets();
if (timeBuckets.size() > 0) {
TimeBucket firstBucket = timeBuckets.get(0);
anomalyTimelinesView.addSummary("currentStart", Long.toString(firstBucket.getCurrentStart()));
anomalyTimelinesView.addSummary("baselineStart", Long.toString(firstBucket.getBaselineStart()));
TimeBucket lastBucket = timeBuckets.get(timeBuckets.size() - 1);
anomalyTimelinesView.addSummary("currentEnd", Long.toString(lastBucket.getCurrentStart()));
anomalyTimelinesView.addSummary("baselineEnd", Long.toString(lastBucket.getBaselineEnd()));
}
return anomalyTimelinesView;
}
use of com.linkedin.thirdeye.api.TimeGranularity in project pinot by linkedin.
the class Utils method getTimeGranularityFromString.
public static TimeGranularity getTimeGranularityFromString(String aggTimeGranularity) {
TimeGranularity timeGranularity = null;
if (aggTimeGranularity.indexOf("_") > -1) {
String[] split = aggTimeGranularity.split("_");
timeGranularity = new TimeGranularity(Integer.parseInt(split[0]), TimeUnit.valueOf(split[1]));
} else {
timeGranularity = new TimeGranularity(1, TimeUnit.valueOf(aggTimeGranularity));
}
return timeGranularity;
}
use of com.linkedin.thirdeye.api.TimeGranularity in project pinot by linkedin.
the class AnomaliesResource method getAnomalyDataCompareResults.
@GET
@Path("/{anomalyId}")
public AnomalyDataCompare.Response getAnomalyDataCompareResults(@PathParam("anomalyId") Long anomalyId) {
MergedAnomalyResultDTO anomaly = mergedAnomalyResultDAO.findById(anomalyId);
if (anomaly == null) {
LOG.error("Anomaly not found with id " + anomalyId);
throw new IllegalArgumentException("Anomaly not found with id " + anomalyId);
}
AnomalyDataCompare.Response response = new AnomalyDataCompare.Response();
response.setCurrentStart(anomaly.getStartTime());
response.setCurrenEnd(anomaly.getEndTime());
try {
DatasetConfigDTO dataset = datasetConfigDAO.findByDataset(anomaly.getCollection());
TimeGranularity granularity = new TimeGranularity(dataset.getTimeDuration(), dataset.getTimeUnit());
// Lets compute currentTimeRange
Pair<Long, Long> currentTmeRange = new Pair<>(anomaly.getStartTime(), anomaly.getEndTime());
MetricTimeSeries ts = TimeSeriesUtil.getTimeSeriesByDimension(anomaly.getFunction(), Arrays.asList(currentTmeRange), anomaly.getDimensions(), granularity, false);
double currentVal = getTotalFromTimeSeries(ts, dataset.isAdditive());
response.setCurrentVal(currentVal);
for (AlertConfigBean.COMPARE_MODE compareMode : AlertConfigBean.COMPARE_MODE.values()) {
long baselineOffset = EmailHelper.getBaselineOffset(compareMode);
Pair<Long, Long> baselineTmeRange = new Pair<>(anomaly.getStartTime() - baselineOffset, anomaly.getEndTime() - baselineOffset);
MetricTimeSeries baselineTs = TimeSeriesUtil.getTimeSeriesByDimension(anomaly.getFunction(), Arrays.asList(baselineTmeRange), anomaly.getDimensions(), granularity, false);
AnomalyDataCompare.CompareResult cr = new AnomalyDataCompare.CompareResult();
double baseLineval = getTotalFromTimeSeries(baselineTs, dataset.isAdditive());
cr.setBaselineValue(baseLineval);
cr.setCompareMode(compareMode);
cr.setChange(calculateChange(currentVal, baseLineval));
response.getCompareResults().add(cr);
}
} catch (Exception e) {
LOG.error("Error fetching the timeseries data from pinot", e);
throw new RuntimeException(e);
}
return response;
}
use of com.linkedin.thirdeye.api.TimeGranularity in project pinot by linkedin.
the class TimeOnTimeTest method generateGroupByTimeAndDimension.
// CONTRIBUTOR
private static TimeOnTimeComparisonRequest generateGroupByTimeAndDimension() {
TimeOnTimeComparisonRequest comparisonRequest = new TimeOnTimeComparisonRequest();
String collection = "thirdeyeAbook";
comparisonRequest.setCollectionName(collection);
comparisonRequest.setBaselineStart(new DateTime(2016, 4, 1, 00, 00));
comparisonRequest.setBaselineEnd(new DateTime(2016, 4, 2, 00, 00));
comparisonRequest.setCurrentStart(new DateTime(2016, 4, 8, 00, 00));
comparisonRequest.setCurrentEnd(new DateTime(2016, 4, 9, 00, 00));
comparisonRequest.setGroupByDimensions(Lists.newArrayList("browserName", "contactsOrigin", "deviceName", "continent", "countryCode", "environment", "locale", "osName", "pageKey", "source", "sourceApp"));
comparisonRequest.setGroupByDimensions(Lists.newArrayList("environment"));
List<MetricFunction> metricFunctions = new ArrayList<>();
metricFunctions.add(new MetricFunction(MetricAggFunction.SUM, "__COUNT"));
comparisonRequest.setMetricExpressions(Utils.convertToMetricExpressions(metricFunctions));
comparisonRequest.setAggregationTimeGranularity(new TimeGranularity(1, TimeUnit.HOURS));
return comparisonRequest;
}
Aggregations