You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ap...@apache.org on 2019/01/08 18:15:11 UTC
[incubator-pinot] branch master updated: [TE] rootcause - fix
slider and offset quirks (#3663)
This is an automated email from the ASF dual-hosted git repository.
apucher 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 06dc0e9 [TE] rootcause - fix slider and offset quirks (#3663)
06dc0e9 is described below
commit 06dc0e9b2807ff2c023186be9c80394978e82476
Author: Alexander Pucher <ap...@linkedin.com>
AuthorDate: Tue Jan 8 10:15:06 2019 -0800
[TE] rootcause - fix slider and offset quirks (#3663)
This PR fixes a number of quirks in the RCA UI related to the range slider and offsets:
* range slider no longer stuck on first click after changing compare mode
* range slider no longer stale when anomaly range changes
* (most) new offsets now supported in algo tab
Thanks to @aaronucsd for help with this one!
---
.../rootcause-select-comparison-range/component.js | 90 +++------
.../component.js | 216 ---------------------
.../template.hbs | 74 -------
thirdeye/thirdeye-frontend/app/utils/rca-utils.js | 76 +++++---
4 files changed, 75 insertions(+), 381 deletions(-)
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range/component.js b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range/component.js
index 0367de6..a766bee 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range/component.js
+++ b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range/component.js
@@ -4,6 +4,7 @@ import $ from 'jquery';
import {
makeTime
} from 'thirdeye-frontend/utils/rca-utils';
+import _ from 'lodash';
// TODO consolidate rootcause-select-comparison-range2, rootcause-slider
@@ -35,8 +36,7 @@ export default Component.extend({
compareMode: null, // ""
onChange: null, // func (start, end, compareMode)
slider: null,
- originalMinInvestigatePeriod: null,
- originalMaxInvestigatePeriod: null,
+ sliderOptionsCache: null,
rangeOptions: {
'Last hour': [makeTime().subtract(1, 'hours').startOf('hour'), makeTime().startOf('hours').add(1, 'hours')],
@@ -68,19 +68,19 @@ export default Component.extend({
}
],
- minDisplayWindow: computed('displayRange.[]', function() {//display window start - slider
+ minDisplayWindow: computed('displayRange', function() {//display window start - slider
return makeTime(this.get('displayRange')[0]);
}),
- maxDisplayWindow: computed('displayRange.[]', function() {//display window end - slider
+ maxDisplayWindow: computed('displayRange', function() {//display window end - slider
return makeTime(this.get('displayRange')[1]);
}),
- minInvestigatePeriod: computed('anomalyRange.[]', function() {//Investigation period start - slider
+ minInvestigatePeriod: computed('anomalyRange', function() {//Investigation period start - slider
return makeTime(this.get('anomalyRange')[0]);
}),
- maxInvestigatePeriod: computed('anomalyRange.[]', function() {//Investigation period - slider
+ maxInvestigatePeriod: computed('anomalyRange', function() {//Investigation period - slider
return makeTime(this.get('anomalyRange')[1]);
}),
@@ -88,12 +88,11 @@ export default Component.extend({
return namedToEpocMapping[this.get('granularity')];
}),
-
- startFormatted: computed('anomalyRange.[]', function() {//investigation start
+ startFormatted: computed('anomalyRange', function() {//investigation start
return makeTime(this.get('anomalyRange')[0]).format(serverDateFormat);
}),
- endFormatted: computed('anomalyRange.[]', function() {//investigation end
+ endFormatted: computed('anomalyRange', function() {//investigation end
return makeTime(this.get('anomalyRange')[1]).format(serverDateFormat);
}),
@@ -101,8 +100,13 @@ export default Component.extend({
return makeTime().startOf('hour').add(1, 'hours').format(serverDateFormat);
}),
- compareModeFormatted: computed('compareMode', function() {
- return this.get('compareMode');
+ compareModeFormatted: computed('compareMode', {
+ get () {
+ return this.get('compareMode');
+ },
+ set () {
+ // ignore to prevent override
+ }
}),
/**
@@ -112,7 +116,8 @@ export default Component.extend({
this._super(...arguments);
let $range = $('.js-range-slider');
const timeFormat = this.get('timeFormat');
- const { compareMode, onChange } = this.getProperties('compareMode', 'onChange');
+ const { onChange } = this.getProperties('onChange');
+ const $$ = this;
$range.ionRangeSlider({
type: 'double',
@@ -129,7 +134,7 @@ export default Component.extend({
},
onFinish: function (data) {
// Update the display window's investigation period on the chart
- onChange(makeTime(data.from).valueOf(), makeTime(data.to).valueOf(), compareMode);
+ onChange(makeTime(data.from).valueOf(), makeTime(data.to).valueOf(), $$.get('compareMode'));
}
});
@@ -148,37 +153,24 @@ export default Component.extend({
// granularityOneWay: this.get('granularity')
});
- // Save original investigation periods
- this.setProperties({
- originalMinInvestigatePeriod: this.get('minInvestigatePeriod'),
- originalMaxInvestigatePeriod: this.get('maxInvestigatePeriod')
- });
-
// Update the slider, by calling it's update method
- this.get('slider').update({
+ const sliderOptionsCache = this.get('sliderOptionsCache');
+
+ const sliderOptions = {
step: this.get('granularityOneWay'),
min: this.get('minDisplayWindow').format('x'),
- max: this.get('maxDisplayWindow').format('x')
- });
+ max: this.get('maxDisplayWindow').format('x'),
+ from: this.get('minInvestigatePeriod').format('x'),
+ to: this.get('maxInvestigatePeriod').format('x')
+ };
+
+ if (!_.isEqual(sliderOptions, sliderOptionsCache)) {
+ this.get('slider').update(sliderOptions);
+ this.set('sliderOptionsCache', sliderOptions);
+ }
},
actions: {
- onRange(start, end) {
- const { compareMode, onChange } = this.getProperties('compareMode', 'onChange');
-
- // Update anomalyRange for computed to recalculate
- this.set('anomalyRange', [makeTime(start).valueOf(), makeTime(end).valueOf()]);
-
- // Investigation period changed on date picker. Update the slider's min and max.
- this.get('slider').update({
- from: this.get('minInvestigatePeriod').format('x'),
- to: this.get('maxInvestigatePeriod').format('x')
- });
-
- // Update the display window's investigation period on the chart
- onChange(makeTime(start).valueOf(), makeTime(end).valueOf(), compareMode);
- },
-
onPickerRange(type, time) {
const { compareMode, onChange } = this.getProperties('compareMode', 'onChange');
@@ -189,10 +181,6 @@ export default Component.extend({
// Update for the date picker to be in sync
this.set('anomalyRange', [makeTime(start).valueOf(), makeTime(end).valueOf()]);
- // Investigation period changed on date picker. Update the slider's min and max.
- let sliderOptions = type === 'start' ? { from: this.get('minInvestigatePeriod').format('x') } : { to: this.get('maxInvestigatePeriod').format('x') };
- this.get('slider').update(sliderOptions);
-
// Update the display window's investiation period on the chart
onChange(makeTime(start).valueOf(), makeTime(end).valueOf(), compareMode);
},
@@ -200,24 +188,6 @@ export default Component.extend({
onCompareMode(compareMode) {
const { anomalyRange, onChange } = this.getProperties('anomalyRange', 'onChange');
onChange(anomalyRange[0], anomalyRange[1], compareMode);
- },
-
- resetSlider() {
- const slider = this.get('slider');
- // RESET - reset slider to it's first values
- slider.reset();
- // get original investigation periods
- this.setProperties({
- minInvestigatePeriod: this.get('originalMinInvestigatePeriod'),
- maxInvestigatePeriod: this.get('originalMaxInvestigatePeriod')
- });
-
- // Update the slider, by calling it's update method
- this.get('slider').update({
- from: this.get('minInvestigatePeriod').format('x'),
- to: this.get('maxInvestigatePeriod').format('x')
- });
}
-
}
});
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range2/component.js b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range2/component.js
deleted file mode 100644
index 4c8f32a..0000000
--- a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range2/component.js
+++ /dev/null
@@ -1,216 +0,0 @@
-import { computed } from '@ember/object';
-import Component from '@ember/component';
-import $ from 'jquery';
-import {
- makeTime,
- dateFormatFull
-} from 'thirdeye-frontend/utils/rca-utils';
-
-// TODO merge this with rootcause-select-comparison-range
-
-/**
- * Date format the date picker component expects
- * @type String
- *
- */
-const serverDateFormat = 'YYYY-MM-DD HH:mm';
-
-/**
- * @summary Mapping between values that are named on the backend to epoc time value in millis
- * @type {Object}
- * @example `1_HOURS=3600000=1hr , 1800000=30mins` etc since we using epoc time values in millis
- */
-const namedToEpocMapping = {
- '5_MINUTES': 300000,
- '15_MINUTES': 900000,
- '30_MINUTES': 1800000,
- '1_HOURS': 3600000,
- '3_HOURS': 10800000,
- '1_DAYS': 86400000
-};
-
-
-export default Component.extend({
- timeFormat: "MMM D, hh:mm a z",//slider
- range: null, // [0, 0]
- compareMode: null, // ""
- onChange: null, // func (start, end, compareMode)
- slider: null,
- originalMinInvestigatePeriod: null,
- originalMaxInvestigatePeriod: null,
-
- rangeOptions: {
- 'Last hour': [makeTime().subtract(1, 'hours').startOf('hour'), makeTime().startOf('hours').add(1, 'hours')],
- 'Last 3 hours': [makeTime().subtract(3, 'hours').startOf('hour'), makeTime().startOf('hours').add(1, 'hours')],
- 'Last 6 hours': [makeTime().subtract(6, 'hours').startOf('hour'), makeTime().startOf('hours').add(1, 'hours')],
- 'Last 24 hours': [makeTime().subtract(24, 'hours').startOf('hour'), makeTime().startOf('hours').add(1, 'hours')]
- },
-
- compareModeOptions: [
- 'WoW',
- 'Wo2W',
- 'Wo3W',
- 'Wo4W',
- 'mean4w',
- 'median4w',
- 'min4w',
- 'max4w',
- 'predicted',
- 'none'
- ],
-
- minDisplayWindow: computed('displayRange.[]', function() {//display window start - slider
- return makeTime(this.get('displayRange')[0]);
- }),
-
- maxDisplayWindow: computed('displayRange.[]', function() {//display window end - slider
- return makeTime(this.get('displayRange')[1]);
- }),
-
- minInvestigatePeriod: computed('anomalyRange.[]', function() {//Investigation period start - slider
- return makeTime(this.get('anomalyRange')[0]);
- }),
-
- maxInvestigatePeriod: computed('anomalyRange.[]', function() {//Investigation period - slider
- return makeTime(this.get('anomalyRange')[1]);
- }),
-
- granularityOneWay: computed('granularity', function() {
- return namedToEpocMapping[this.get('granularity')];
- }),
-
-
- startFormatted: computed('anomalyRange.[]', function() {//investigation start
- return makeTime(this.get('anomalyRange')[0]).format(serverDateFormat);
- }),
-
- endFormatted: computed('anomalyRange.[]', function() {//investigation end
- return makeTime(this.get('anomalyRange')[1]).format(serverDateFormat);
- }),
-
- maxDateFormatted: computed(function() {
- return makeTime().startOf('hour').add(1, 'hours').format(serverDateFormat);
- }),
-
- compareModeFormatted: computed('compareMode', function() {
- return this.get('compareMode');
- }),
-
- /**
- * Default after elements are inserted
- */
- didInsertElement() {
- this._super(...arguments);
- let $range = $('.js-range-slider');
- const timeFormat = this.get('timeFormat');
- const { compareMode, onChange } = this.getProperties('compareMode', 'onChange');
-
- $range.ionRangeSlider({
- type: 'double',
- grid: true,
- grid_num: 1,
- hide_min_max: true,
- step: this.get('granularityOneWay'),
- min: this.get('minDisplayWindow').format('x'),
- max: this.get('maxDisplayWindow').format('x'),
- from: this.get('minInvestigatePeriod').format('x'),
- to: this.get('maxInvestigatePeriod').format('x'),
- prettify: function (num) {
- return makeTime(num).format(timeFormat);
- },
- onFinish: function (data) {
- // Update the display window's investigation period on the chart
- onChange(makeTime(data.from).valueOf(), makeTime(data.to).valueOf(), compareMode);
- }
- });
-
- // Save slider instance to var
- this.set('slider', $range.data('ionRangeSlider'));
- },
-
- didRender() {
- this._super(...arguments);
-
- // Set oneway assignment from these existing CPs
- this.setProperties({
- startFormattedOneWay: this.get('startFormatted'),
- endFormattedOneWay: this.get('endFormatted'),
- maxDateFormattedOneWay: this.get('maxDateFormatted'),
- // granularityOneWay: this.get('granularity')
- });
-
- // Save original investigation periods
- this.setProperties({
- originalMinInvestigatePeriod: this.get('minInvestigatePeriod'),
- originalMaxInvestigatePeriod: this.get('maxInvestigatePeriod')
- });
-
- // Update the slider, by calling it's update method
- if (this.get('slider')) {
- this.get('slider').update({
- step: this.get('granularityOneWay'),
- min: this.get('minDisplayWindow').format('x'),
- max: this.get('maxDisplayWindow').format('x')
- });
- }
- },
-
- actions: {
- onRange(start, end) {
- const { compareMode, onChange } = this.getProperties('compareMode', 'onChange');
-
- // Update anomalyRange for computed to recalculate
- this.set('anomalyRange', [makeTime(start).valueOf(), makeTime(end).valueOf()]);
-
- // Investigation period changed on date picker. Update the slider's min and max.
- this.get('slider').update({
- from: this.get('minInvestigatePeriod').format('x'),
- to: this.get('maxInvestigatePeriod').format('x')
- });
-
- // Update the display window's investiation period on the chart
- onChange(makeTime(start).valueOf(), makeTime(end).valueOf(), compareMode);
- },
-
- onPickerRange(type, time) {
- const { compareMode, onChange } = this.getProperties('compareMode', 'onChange');
-
- // Update anomalyRange for computed to recalculate
- const start = type === 'start' ? makeTime(time).valueOf() : this.get('minInvestigatePeriod').valueOf();
- const end = type === 'start' ? this.get('maxInvestigatePeriod').valueOf() : makeTime(time).valueOf();
-
- // Update for the date picker to be in sync
- this.set('anomalyRange', [makeTime(start).valueOf(), makeTime(end).valueOf()]);
-
- // Investigation period changed on date picker. Update the slider's min and max.
- let sliderOptions = type === 'start' ? { from: this.get('minInvestigatePeriod').format('x') } : { to: this.get('maxInvestigatePeriod').format('x') };
- this.get('slider').update(sliderOptions);
-
- // Update the display window's investiation period on the chart
- onChange(makeTime(start).valueOf(), makeTime(end).valueOf(), compareMode);
- },
-
- onCompareMode(compareMode) {
- const { anomalyRange, onChange } = this.getProperties('anomalyRange', 'onChange');
- onChange(anomalyRange[0], anomalyRange[1], compareMode);
- },
-
- resetSlider() {
- const slider = this.get('slider');
- // RESET - reset slider to it's first values
- slider.reset();
- // get original investigation periods
- this.setProperties({
- minInvestigatePeriod: this.get('originalMinInvestigatePeriod'),
- maxInvestigatePeriod: this.get('originalMaxInvestigatePeriod')
- });
-
- // Update the slider, by calling it's update method
- this.get('slider').update({
- from: this.get('minInvestigatePeriod').format('x'),
- to: this.get('maxInvestigatePeriod').format('x')
- });
- }
-
- }
-});
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range2/template.hbs b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range2/template.hbs
deleted file mode 100644
index 88caf8b..0000000
--- a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-select-comparison-range2/template.hbs
+++ /dev/null
@@ -1,74 +0,0 @@
-<div class="col-xs-3">
- <label class="te-label te-label--small">Baseline
- <span>
- <i class="glyphicon glyphicon-question-sign"></i>
- {{#tooltip-on-element class="te-tooltip"}}
- This is the compare mode for computing the baseline in the charts above and below. For example, "Wo2W" uses data from the analysis period shifted by two weeks.
- {{/tooltip-on-element}}
- </span>
- </label>
- {{#power-select
- selected=compareModeFormatted
- options=compareModeOptions
- searchEnabled=false
- triggerId="select-compare-mode"
- onchange=(action "onCompareMode")
- as |mode|
- }}
- {{mode}}
- {{/power-select}}
-</div>
-<div class="col-xs-9">
- <!-- Investigation range slider -->
- <div class="date-slider date-slider--offset" style="position: relative;top: 20px;">
- <div class="date-slider__picker">
- <div class="date-slider__picker-item">
- <label class="te-label te-label--small">Investigation Period
- <span>
- <i class="glyphicon glyphicon-question-sign"></i>
- {{#tooltip-on-element class="te-tooltip"}}
- Typically, this is your anomaly period. It is highlighted in orange in the graph above. It also affects the data in views below.
- {{/tooltip-on-element}}
- </span>
- </label>
- </div>
- <div class="date-slider__picker-item">
- {{date-range-picker
- class="te-range-picker te-range-picker__from"
- singleDatePicker=true
- showDropdowns=true
- timePicker=true
- timePicker24Hour=true
- timePickerIncrement=5
- start=startFormattedOneWay
- end=startFormattedOneWay
- maxDate=maxDateFormatted
- ranges=rangeOptions
- format=timeFormat
- serverFormat="YYYY-MM-DD HH:mm"
- applyAction=(action "onPickerRange" "start")
- }}
- </div>
- <div class="date-slider__picker-item">
- <label class="te-label te-label--small">to</label>
- </div>
- <div class="date-slider__picker-item">
- {{date-range-picker
- class="te-range-picker te-range-picker__to"
- singleDatePicker=true
- showDropdowns=true
- timePicker=true
- timePicker24Hour=true
- timePickerIncrement=5
- start=endFormattedOneWay
- end=endFormattedOneWay
- maxDate=maxDateFormatted
- ranges=rangeOptions
- format=timeFormat
- serverFormat="YYYY-MM-DD HH:mm"
- applyAction=(action "onPickerRange" "end")
- }}
- </div>
- </div>
- </div>
-</div>
diff --git a/thirdeye/thirdeye-frontend/app/utils/rca-utils.js b/thirdeye/thirdeye-frontend/app/utils/rca-utils.js
index 151eaae..4c2103c 100644
--- a/thirdeye/thirdeye-frontend/app/utils/rca-utils.js
+++ b/thirdeye/thirdeye-frontend/app/utils/rca-utils.js
@@ -376,48 +376,62 @@ export function filterPrefix(urns, prefixes) {
}
/**
- * Converts a time range tuple to another time range with a given offset
+ * Converts a time range tuple to another time range with a given offset (in Pacific time zone)
*
* @param {Array} range time range tuple [start, end]
* @param {string} offset time offset ('current', 'baseline', 'wo1w', 'wo2w', 'wo3w', 'wo4w)
* @returns {Array} offset time range tuple
*/
export function toBaselineRange(range, offset) {
- const offsetWeeks = {
- current: 0,
- none: 0,
- predicted: 0,
- wow: 1,
- wo1w: 1,
- wo2w: 2,
- wo3w: 3,
- wo4w: 4,
- mean4w: 1, // default. not fully supported by backend yet
- median4w: 1, // default. not fully supported by backend yet
- min4w: 1, // default. not fully supported by backend yet
- max4w: 1, // default. not fully supported by backend yet
- ho1h: 1,
- ho2h: 1,
- ho3h: 1,
- median4h: 1,
- mean4h: 1,
- do1d: 1,
- do2d: 1,
- do3d: 1,
- median4d: 1,
- mean4d: 1,
- mo1m: 1,
- mo2m: 1,
- mo3m: 1,
- median4m: 1,
- mean4m: 1
+ const timeOffset = {
+ current: [0, 'weeks'],
+ predicted: [0, 'weeks'], // no backend support
+ none: [0, 'weeks'], // no backend support
+
+ wow: [1, 'weeks'],
+ wo1w: [1, 'weeks'],
+ wo2w: [2, 'weeks'],
+ wo3w: [3, 'weeks'],
+ wo4w: [4, 'weeks'],
+ mean4w: [1, 'weeks'], // no backend support
+ median4w: [1, 'weeks'], // no backend support
+ min4w: [1, 'weeks'], // no backend support
+ max4w: [1, 'weeks'], // no backend support
+
+ ho1h: [1, 'hours'],
+ ho2h: [2, 'hours'],
+ ho3h: [3, 'hours'],
+ ho6h: [6, 'hours'],
+ median6h: [1, 'hours'], // no backend support
+ mean6h: [1, 'hours'], // no backend support
+ min6h: [1, 'hours'], // no backend support
+ max6h: [1, 'hours'], // no backend support
+
+ do1d: [1, 'days'],
+ do2d: [2, 'days'],
+ do3d: [3, 'days'],
+ do4d: [4, 'days'],
+ median4d: [1, 'days'], // no backend support
+ mean4d: [1, 'days'], // no backend support
+ min4d: [1, 'days'], // no backend support
+ max4d: [1, 'days'], // no backend support
+
+ mo1m: [1, 'months'],
+ mo2m: [2, 'months'],
+ mo3m: [3, 'months'],
+ mo6m: [6, 'months'],
+ median6m: [1, 'months'], // no backend support
+ mean6m: [1, 'months'], // no backend support
+ min6m: [1, 'months'], // no backend support
+ max6m: [1, 'months'] // no backend support
+
}[offset.toLowerCase()];
- if (offsetWeeks === 0) {
+ if (!timeOffset || timeOffset[0] === 0) {
return range;
}
- const start = makeTime(range[0]).subtract(offsetWeeks, 'weeks').valueOf();
+ const start = makeTime(range[0]).subtract(timeOffset[0], timeOffset[1]).valueOf();
const end = start + (range[1] - range[0]);
return [start, end];
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org