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 2019/06/19 17:10:12 UTC
[incubator-pinot] branch master updated: [TE] frontend -
harleyjj/alert-overview - show bounds on Alert Overview (#4314)
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 2377037 [TE] frontend - harleyjj/alert-overview - show bounds on Alert Overview (#4314)
2377037 is described below
commit 2377037f0c816b722e156ca151fa15effca4de1a
Author: Harley Jackson <hj...@linkedin.com>
AuthorDate: Wed Jun 19 10:10:07 2019 -0700
[TE] frontend - harleyjj/alert-overview - show bounds on Alert Overview (#4314)
* [TE] pinot - harleyjj/granularity - get dataset details by name
* [TE] frontend - harleyjj/alert-overview - show bounds, rules, and predicted on Alert Overview for daily granularity with no dimensions
---
.../app/pods/components/alert-details/component.js | 70 +++++++++++++++-------
.../app/pods/components/alert-details/template.hbs | 4 +-
.../pods/components/timeseries-chart/component.js | 12 +++-
.../app/pods/manage/explore/route.js | 7 ++-
.../app/pods/manage/explore/template.hbs | 1 +
thirdeye/thirdeye-frontend/app/utils/anomaly.js | 19 +++++-
.../thirdeye-frontend/app/utils/api/anomaly.js | 18 +++++-
thirdeye/thirdeye-frontend/app/utils/utils.js | 14 ++++-
.../thirdeye/detection/DetectionResource.java | 10 +++-
9 files changed, 124 insertions(+), 31 deletions(-)
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js
index d1c8a29..9cd60ae 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js
+++ b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/component.js
@@ -22,6 +22,7 @@ import { colorMapping, makeTime, toMetricLabel, extractTail } from 'thirdeye-fro
import { getYamlPreviewAnomalies,
getAnomaliesByAlertId,
getFormattedDuration,
+ getBoundsAndAnomalies,
anomalyResponseMapNew,
anomalyResponseObj,
anomalyResponseObjNew,
@@ -91,6 +92,7 @@ export default Component.extend({
isLoadingTimeSeries: false,
granularity: null,
alertYaml: null,
+ dimensionExploration: null,
@@ -99,10 +101,11 @@ export default Component.extend({
* @type {Array}
*/
baselineOptions: computed(
- 'isPreviewMode',
+ 'showRules',
function() {
+ const showRules = get(this, 'showRules');
let options;
- if (get(this, 'isPreviewMode')) {
+ if (showRules) {
options = [
{ name: 'predicted', isActive: true},
{ name: 'wo1w', isActive: false},
@@ -163,7 +166,7 @@ export default Component.extend({
return {
detectorName: detector,
name: nameOnly
- }
+ };
});
}
return [];
@@ -183,6 +186,24 @@ export default Component.extend({
),
/**
+ * flag to differentiate whether we show bounds and rules or not
+ * @type {Boolean}
+ */
+ showRules: computed(
+ 'isPreviewMode',
+ 'granularity',
+ 'dimensionExploration',
+ function() {
+ const {
+ isPreviewMode,
+ granularity,
+ dimensionExploration
+ } = this.getProperties('isPreviewMode', 'granularity', 'dimensionExploration');
+ return (isPreviewMode || (!dimensionExploration && (granularity === 'DAYS')));
+ }
+ ),
+
+ /**
* dimensions to display in dimensions dropdown
* @type {Array}
*/
@@ -361,18 +382,19 @@ export default Component.extend({
'metricUrn',
'selectedRule',
'selectedDimension',
+ 'showRules',
function() {
let currentAnomalies = [];
const {
- metricUrn, anomalies, selectedRule
- } = getProperties(this, 'metricUrn', 'anomalies', 'selectedRule');
+ metricUrn, anomalies, selectedRule, showRules
+ } = getProperties(this, 'metricUrn', 'anomalies', 'selectedRule', 'showRules');
if (!_.isEmpty(anomalies)) {
currentAnomalies = anomalies.filter(anomaly => {
if (anomaly.metricUrn === metricUrn) {
- if(get(this, 'isPreviewMode') && anomaly.properties && typeof anomaly.properties === 'object' && selectedRule && typeof selectedRule === 'object') {
+ if(showRules && anomaly.properties && typeof anomaly.properties === 'object' && selectedRule && typeof selectedRule === 'object') {
return (anomaly.properties.detectorComponentName.includes(selectedRule.detectorName));
- } else if (!get(this, 'isPreviewMode')) {
+ } else if (!showRules) {
// This is necessary until we surface rule selector in Alert Overview
return true;
}
@@ -417,8 +439,8 @@ export default Component.extend({
'metricUrn',
function () {
const {
- currentAnomalies, timeseries, baseline
- } = getProperties(this, 'currentAnomalies', 'timeseries', 'baseline');
+ currentAnomalies, timeseries, baseline, showRules
+ } = getProperties(this, 'currentAnomalies', 'timeseries', 'baseline', 'showRules');
const series = {};
if (!_.isEmpty(currentAnomalies)) {
@@ -440,7 +462,7 @@ export default Component.extend({
}
// The current time series has a different naming convention in Preview
- if (get(this, 'isPreviewMode')) {
+ if (showRules) {
if (timeseries && !_.isEmpty(timeseries.current)) {
series['Current'] = {
timestamps: timeseries.timestamp,
@@ -628,9 +650,10 @@ export default Component.extend({
analysisRange,
anomaliesRange,
notifications,
- isPreviewMode,
- alertId
- } = this.getProperties('analysisRange', 'anomaliesRange', 'notifications', 'isPreviewMode', 'alertId');
+ showRules,
+ alertId,
+ granularity
+ } = this.getProperties('analysisRange', 'anomaliesRange', 'notifications', 'showRules', 'alertId', 'granularity');
//detection alert fetch
const start = analysisRange[0];
const end = analysisRange[1];
@@ -642,8 +665,8 @@ export default Component.extend({
let metricUrnList;
let firstDimension;
try {
- if(isPreviewMode){
- applicationAnomalies = yield getYamlPreviewAnomalies(alertYaml, startAnomalies, endAnomalies, alertId);
+ if(showRules){
+ applicationAnomalies = (granularity === 'DAYS') ? yield getBoundsAndAnomalies(alertId, startAnomalies, endAnomalies) : yield getYamlPreviewAnomalies(alertYaml, startAnomalies, endAnomalies, alertId);
if (applicationAnomalies && applicationAnomalies.diagnostics && applicationAnomalies.diagnostics['0']) {
metricUrnList = Object.keys(applicationAnomalies.diagnostics['0']);
set(this, 'metricUrnList', metricUrnList);
@@ -716,13 +739,18 @@ export default Component.extend({
init() {
this._super(...arguments);
- const isPreviewMode = get(this, 'isPreviewMode');
+ const {
+ granularity,
+ isPreviewMode,
+ dimensionExploration
+ } = this.getProperties('granularity', 'isPreviewMode', 'dimensionExploration');
if (!isPreviewMode) {
this.setProperties({
analysisRange: [moment().add(1, 'day').subtract(1, 'month').startOf('day').valueOf(), moment().add(1, 'day').startOf('day').valueOf()],
duration: '1m',
selectedDimension: 'Choose a dimension',
- selectedBaseline: 'wo1w'
+ // For now, we will only show predicted and bounds on daily metrics with no dimensions, for the Alert Overview page
+ selectedBaseline: (granularity === 'DAYS' && !dimensionExploration) ? 'predicted' : 'wo1w'
});
this._fetchAnomalies();
} else {
@@ -746,10 +774,10 @@ export default Component.extend({
metricUrn,
analysisRange,
selectedBaseline,
- isPreviewMode,
+ showRules,
selectedRule,
uniqueTimeSeries
- } = this.getProperties('metricUrn', 'analysisRange', 'selectedBaseline', 'isPreviewMode', 'selectedRule', 'uniqueTimeSeries');
+ } = this.getProperties('metricUrn', 'analysisRange', 'selectedBaseline', 'showRules', 'selectedRule', 'uniqueTimeSeries');
const timeZone = 'America/Los_Angeles';
this.setProperties({
@@ -757,7 +785,7 @@ export default Component.extend({
isLoadingTimeSeries: true
});
- if (isPreviewMode) {
+ if (showRules) {
const seriesSet = uniqueTimeSeries.find(series => {
if (series.detectorName === selectedRule.detectorName && series.metricUrn === metricUrn) {
return series;
@@ -997,7 +1025,7 @@ export default Component.extend({
const metricUrnList = get(this, 'metricUrnList');
const newMetricUrn = metricUrnList.find(urn => {
const dimensionUrn = toMetricLabel(extractTail(decodeURIComponent(urn)));
- if ( dimensionUrn === selected) {
+ if (dimensionUrn === selected) {
return urn;
// if there is no tail, this will be called 'All Dimensions' in the UI
} else if (dimensionUrn === '' && selected === 'All Dimensions') {
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs
index be93e9b..66f9a03 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs
+++ b/thirdeye/thirdeye-frontend/app/pods/components/alert-details/template.hbs
@@ -87,7 +87,7 @@
{{/if}}
<div class="te-content-block">
- {{#if isPreviewMode}}
+ {{#if showRules}}
<h4 class="te-self-serve__block-title">{{selectedRule.name}} {{#if alertHasDimensions}}/ {{selectedDimension}}{{/if}} anomalies over time ({{numCurrentAnomalies}})</h4>
{{else}}
<h4 class="te-self-serve__block-title">{{#if alertHasDimensions}}{{selectedDimension}} a{{else}}A{{/if}}nomalies over time ({{numCurrentAnomalies}})</h4>
@@ -99,7 +99,7 @@
<div class="te-form__select te-form__select--same-line col-md-3">
{{!-- Rule selector --}}
- {{#if isPreviewMode}}
+ {{#if showRules}}
{{#power-select
triggerId="select-rule"
triggerClass="te-form__select"
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js b/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js
index 46fbf60..1e744bb 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js
+++ b/thirdeye/thirdeye-frontend/app/pods/components/timeseries-chart/component.js
@@ -243,7 +243,17 @@ export default Component.extend({
if (upperBoundVals && lowerBoundVals) {
upperBoundVals = upperBoundVals.values.map(e => e.value);
lowerBoundVals = lowerBoundVals.values.map(e => e.value);
-
+ // If all upper bound vals are null, we assume that there is only a lower bound
+ if (upperBoundVals.every(val => val === null)) {
+ let currentVals = chart.internal.data.targets.find(target => {
+ return target.id === 'Current';
+ });
+ if (currentVals) {
+ currentVals = currentVals.values.map(e => e.value);
+ const currentMax = Math.max(...currentVals);
+ upperBoundVals = upperBoundVals.map(() => 2 * currentMax);
+ }
+ }
const area_main = d3.svg.area()
.interpolate('linear')
.x(d => xscale(xVals[d]))
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js b/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
index ff8651e..89f00f5 100644
--- a/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
@@ -49,7 +49,12 @@ export default Route.extend({
});
try {
- granularity = detection_json.properties.nested[0].nested[0].nested[0].windowUnit;
+ if (detectionInfo.dataset) {
+ const datasetUrl = `/detection/dataset?name=${detectionInfo.dataset}`;
+ const dataset_result = await fetch(datasetUrl, getProps);
+ const dataset_json = await dataset_result.json();
+ granularity = dataset_json.timeUnit;
+ }
} catch (error) {
granularity = null;
}
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs b/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs
index 8aeef63..fa2e091 100644
--- a/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs
@@ -33,6 +33,7 @@
metricUrn=model.metricUrn
metricUrnList=model.metricUrnList
granularity=model.granularity
+ dimensionExploration=model.alertData.dimensionExploration
}}
{{/if}}
</div>
diff --git a/thirdeye/thirdeye-frontend/app/utils/anomaly.js b/thirdeye/thirdeye-frontend/app/utils/anomaly.js
index fe16601..41077fa 100644
--- a/thirdeye/thirdeye-frontend/app/utils/anomaly.js
+++ b/thirdeye/thirdeye-frontend/app/utils/anomaly.js
@@ -4,7 +4,8 @@ import _ from 'lodash';
import {
checkStatus,
postProps,
- postYamlProps
+ postYamlProps,
+ getProps
} from 'thirdeye-frontend/utils/utils';
import fetch from 'fetch';
import {
@@ -12,7 +13,8 @@ import {
getAnomaliesForYamlPreviewUrl,
getAnomaliesByAlertIdUrl,
getAnomalyFiltersByTimeRangeUrl,
- getAnomalyFiltersByAnomalyIdUrl
+ getAnomalyFiltersByAnomalyIdUrl,
+ getBoundsAndAnomaliesUrl
} from 'thirdeye-frontend/utils/api/anomaly';
/**
@@ -110,6 +112,19 @@ export function getYamlPreviewAnomalies(yamlString, startTime, endTime, alertId)
}
/**
+ * Get bounds and anomalies for a given detection
+ * @method getBoundsAndAnomalies
+ * @param {String} detectionId - the id of the detection
+ * @param {Number} startTime - start time of analysis range
+ * @param {Number} endTime - end time of analysis range
+ * @return {Ember.RSVP.Promise}
+ */
+export function getBoundsAndAnomalies(detectionId, startTime, endTime) {
+ const url = getBoundsAndAnomaliesUrl(detectionId, startTime, endTime);
+ return fetch(url, getProps()).then((res) => checkStatus(res));
+}
+
+/**
* Get anomalies for a given detection id over a specified time range
* @method getAnomaliesByAlertId
* @param {Number} alertId - the alert id aka detection config id
diff --git a/thirdeye/thirdeye-frontend/app/utils/api/anomaly.js b/thirdeye/thirdeye-frontend/app/utils/api/anomaly.js
index 5d4d077..d6e6ded 100644
--- a/thirdeye/thirdeye-frontend/app/utils/api/anomaly.js
+++ b/thirdeye/thirdeye-frontend/app/utils/api/anomaly.js
@@ -13,14 +13,27 @@ export function getAnomalyDataUrl(anomalyId) {
* Returns url for getting the Anomalies for a given YAML configuration so user can preview
* @param {Number} startTime - the anomaly start time
* @param {Number} endTime - the anomaly end time
+ * @param {String} alertId - optional alert id that will call /yaml/preview/{id} if provided
* @returns {String} the complete yaml/preview url
- * @example getAnomaliesForYamlPreview(1508472700000, 1508472800000) // yields => /yaml/preview?start=1508472700000&end=1508472800000&tuningStart=0&tuningEnd=0
+ * @example getAnomaliesForYamlPreviewUrl(1508472700000, 1508472800000) // yields => /yaml/preview?start=1508472700000&end=1508472800000&tuningStart=0&tuningEnd=0
*/
export function getAnomaliesForYamlPreviewUrl(startTime, endTime, alertId) {
return `/yaml/preview${alertId ? `/${alertId}` : ''}?start=${startTime}&end=${endTime}&tuningStart=0&tuningEnd=0`;
}
/**
+ * Returns url for getting the time series and Anomalies for a given detection id
+ * @param {String} detectionId - the detection id
+ * @param {Number} startTime - the anomaly start time
+ * @param {Number} endTime - the anomaly end time
+ * @returns {String} the complete yaml/preview url
+ * @example getBoundsAndAnomalies(111111, 1508472700000, 1508472800000) // yields => /detection/preview/111111?start=1508472700000&end=1508472800000&diagnostics=true
+ */
+export function getBoundsAndAnomaliesUrl(detectionId, startTime, endTime) {
+ return `/detection/preview/${detectionId}?start=${startTime}&end=${endTime}&diagnostics=true`;
+}
+
+/**
* Returns the url for getting Anomalies for a given detection id over the specified time range
* @param {Number} alertId - the alert id aka detection config id
* @param {Number} startTime - the anomaly start time
@@ -57,7 +70,8 @@ export const anomalyApiUrls = {
getAnomaliesForYamlPreviewUrl,
getAnomaliesByAlertIdUrl,
getAnomalyFiltersByTimeRangeUrl,
- getAnomalyFiltersByAnomalyIdUrl
+ getAnomalyFiltersByAnomalyIdUrl,
+ getBoundsAndAnomaliesUrl
};
export default {
diff --git a/thirdeye/thirdeye-frontend/app/utils/utils.js b/thirdeye/thirdeye-frontend/app/utils/utils.js
index 6c4a5d1..6515ebe 100644
--- a/thirdeye/thirdeye-frontend/app/utils/utils.js
+++ b/thirdeye/thirdeye-frontend/app/utils/utils.js
@@ -156,6 +156,17 @@ export function postProps(postData) {
}
/**
+ * Preps get object
+ * @returns {Object}
+ */
+export function getProps() {
+ return {
+ method: 'get',
+ headers: { 'content-type': 'Application/Json' }
+ };
+}
+
+/**
* Preps post object for Yaml payload
* @param {string} text to post
* @returns {Object}
@@ -231,5 +242,6 @@ export default {
toIso,
stripNonFiniteValues,
postYamlProps,
- formatYamlFilter
+ formatYamlFilter,
+ getProps
};
diff --git a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
index c6598a4..53609df 100644
--- a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
+++ b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/DetectionResource.java
@@ -148,6 +148,14 @@ public class DetectionResource {
return Response.ok(config).build();
}
+ @Path("/dataset")
+ @GET
+ @ApiOperation("get a dataset config by name")
+ public Response getDetectionAlertConfig(@ApiParam("the dataset name") @QueryParam("name") String name){
+ DatasetConfigDTO dataset = this.datasetDAO.findByDataset(name);
+ return Response.ok(dataset).build();
+ }
+
@Path("/subscription-groups/{id}")
@GET
@ApiOperation("get a list of detection alert configs for a given detection config id")
@@ -242,7 +250,7 @@ public class DetectionResource {
return Response.ok(gridSearch.bestDetectionConfig().getProperties()).build();
}
- @POST
+ @GET
@Path("/preview/{id}")
@ApiOperation("preview a detection with a existing detection config")
public Response detectionPreview(
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org