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 2020/12/03 20:05:42 UTC

[incubator-pinot] branch master updated: [TE]frontend - Build new subroutes for single-metric-anomalies and composite-anomalies (#6263)

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 47a30ba  [TE]frontend - Build new subroutes for single-metric-anomalies and composite-anomalies (#6263)
47a30ba is described below

commit 47a30ba99f80e83a56f56dbbc009720e3227bc07
Author: Tejas Ajmera <33...@users.noreply.github.com>
AuthorDate: Thu Dec 3 12:05:23 2020 -0800

    [TE]frontend - Build new subroutes for single-metric-anomalies and composite-anomalies (#6263)
    
    This PR adds support to navigate to the appropriate sub-routes for exploration of different anomaly types. Users would first be navigating to the /explore route when they select any alert from the home page or alert page. When the YAML is parsed in that route, we would have access to the type of the alert and thus we can subsequently redirect to the appropriate sub-route (/explore/single-metric-anomalies or /explore/composite-anomalies).
    
    The changes below are also part of this PR:-
    
    Added a util for computing the initial specification to pass into date-range-picker component. This is reusable so we'd be able to delete and greatly simplify the initialization code from all components/routes which instantiate date-range-picker as part of another PR.
    Delete obsolete code
    Refactored performance stats styling, using flexbox instead of display: inline-block. This helps reduce the css.
    Styling improvement for the date-range-picker
---
 .../self-serve-alert-yaml-details/template.hbs     |   3 +-
 .../explore/composite-anomalies/controller.js      | 141 +++++++++++++++++++++
 .../manage/explore/composite-anomalies/route.js    |  28 ++++
 .../explore/composite-anomalies/template.hbs       |  28 ++++
 .../app/pods/manage/explore/route.js               |  15 +++
 .../explore/single-metric-anomalies/controller.js  |   4 +
 .../explore/single-metric-anomalies/route.js       |  16 +++
 .../explore/single-metric-anomalies/template.hbs   |  20 +++
 .../app/pods/manage/explore/template.hbs           |  30 +----
 thirdeye/thirdeye-frontend/app/router.js           |   5 +-
 .../app/styles/shared/_styles.scss                 |  48 +++++--
 .../app/utils/date-picker-utils.js                 |  66 ++++++++++
 .../explore/composite-anomalies/route-test.js      |  11 ++
 .../explore/single-metric-anomalies/route-test.js  |  11 ++
 .../tests/unit/utils/date-picker-utils-test.js     |  36 ++++++
 15 files changed, 418 insertions(+), 44 deletions(-)

diff --git a/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs b/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs
index 9a62b22..059a52b 100644
--- a/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs
+++ b/thirdeye/thirdeye-frontend/app/pods/components/self-serve-alert-yaml-details/template.hbs
@@ -40,7 +40,8 @@
 <div class="te-alert-detail-breakdown row">
   <dl class="col-xs-12 col-sm-5 row">
     <dt class="col-md-4">Metric</dt>
-    <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.metric}}>{{alertData.metric}}
+    <dd class="col-md-8 te-search-results__value{{valueClassSuffix}}" title={{alertData.metric}}>
+      {{if alertData.metric alertData.metric 'N/A'}}
     </dd>
 
     <dt class="col-md-4">Dataset</dt>
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/controller.js b/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/controller.js
new file mode 100644
index 0000000..98e96e0
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/controller.js
@@ -0,0 +1,141 @@
+import Controller from "@ember/controller";
+import { get, set } from "@ember/object";
+import { task } from "ember-concurrency";
+
+import { getAnomaliesByAlertId } from "thirdeye-frontend/utils/anomaly";
+import {
+  getDatePickerSpec
+} from "thirdeye-frontend/utils/date-picker-utils";
+
+import moment from "moment";
+
+export default Controller.extend({
+  /** Internal States */
+
+  /**
+   * Tracks the initial time range passed by the route, after extracting from YAML
+   * Default to 48 hours in milliseconds if nothing is passed.
+   *
+   * @private
+   * @type {Number}
+   */
+  timeWindowSize: 172800000,
+  /**
+   * Tracks the start date in milliseconds for anomalies fetch
+   *
+   * @private
+   * @type {Number}
+   */
+  startDate: undefined,
+  /**
+   * Tracks the end date in milliseconds for anomalies fetch
+   *
+   * @private
+   * @type {Number}
+   */
+  endDate: undefined,
+
+  /** Helper functions */
+
+  /**
+   * Set the end date and start date
+   *
+   * @private
+   */
+  initializeDates() {
+    set(
+      this,
+      "startDate",
+      moment()
+        .subtract(this.timeWindowSize, "milliseconds")
+        .startOf("day")
+        .valueOf()
+    );
+    set(
+      this,
+      "endDate",
+      moment()
+        .add(1, "day")
+        .startOf("day")
+        .valueOf()
+    );
+  },
+
+  /**
+   * Fetch and set the initial state to be passed into the ember bootstrap's
+   * date-range-picker component
+   * Refer https://www.daterangepicker.com/ for all the options it can be configured with
+   *
+   * @private
+   */
+  initializeDatePicker() {
+    const { startDate, endDate } = this;
+
+    set(this, "datePicker", getDatePickerSpec(startDate, endDate));
+  },
+
+  /**
+   * Fetch all the anomalies for the alert in the calculated time range
+   *
+   * @private
+   */
+  fetchAnomaliesTask: task(function*() {
+    try {
+      const { alertId } = get(this, "model");
+      const { startDate, endDate } = this;
+      const applicationAnomalies = yield getAnomaliesByAlertId(
+        alertId,
+        startDate,
+        endDate
+      );
+
+      return applicationAnomalies;
+    } catch (reason) {
+      /* eslint-disable no-console */
+      console.error(reason);
+      /* eslint-disable no-console */
+    }
+  }),
+
+  /**
+   * Perform all the initializations. To be called by the associated route once its
+   * model is ready with all the data.
+   * Note:- These initializations cannot be done inside the native `init` hook of the controller
+   * because the model would not be ready before the controller instantiation.
+   *
+   * @public
+   */
+  activate() {
+    let { timeWindowSize } = get(this, "model");
+    if (timeWindowSize) {
+      set(this, "timeWindowSize", timeWindowSize);
+    }
+
+    this.initializeDates();
+    this.initializeDatePicker();
+
+    this.get('fetchAnomaliesTask').perform();
+  },
+
+  /** Event Handlers */
+  actions: {
+    /**
+     * Function to perform a new fetch for anomalies when a new time
+     * frame is selected by the user
+     *
+     * @param {String} start
+     *   The new start date for the anomalies exploration
+     * @param {String} end
+     *   The new end date for the anomalies exploration
+     */
+    onRangeSelection(start, end) {
+      set(this, "startDate", moment(start).valueOf());
+      set(this, "endDate", moment(end).valueOf());
+
+      set(this, "datePicker.RANGE_START", start);
+      set(this, "datePicker.RANGE_END", end);
+
+      this.fetchAnomaliesTask.perform();
+    }
+  }
+});
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/route.js b/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/route.js
new file mode 100644
index 0000000..015b014
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/route.js
@@ -0,0 +1,28 @@
+import Route from "@ember/routing/route";
+import AuthenticatedRouteMixin from "ember-simple-auth/mixins/authenticated-route-mixin";
+
+export default Route.extend(AuthenticatedRouteMixin, {
+  /**
+   * Ember Route life hook
+   *
+   * @override
+   *
+   * @return {Object}
+   *   The model for this route
+   */
+  model() {
+    return this.modelFor('manage.explore');
+  },
+
+  /**
+   * Perform initialization of the controller after the model is available.
+   *
+   * @override
+   */
+  setupController(controller, model){
+    this._super(controller, model);
+
+    //Cannot rely on the native `init` callback of the controller because the model is not available before controller initialization
+    this.controller.activate();
+  }
+});
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/template.hbs b/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/template.hbs
new file mode 100644
index 0000000..b229e24
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/composite-anomalies/template.hbs
@@ -0,0 +1,28 @@
+<section class="te-page__middle">
+  <section class="container">
+    <section class="te-content-block__date-picker-section">   
+      <span class="te-content-block__date-picker-label">Showing</span>
+      {{date-range-picker
+        class="te-range-picker"
+        timePicker=datePicker.TIME_PICKER
+        timePicker24Hour=datePicker.TIME_PICKER_24_HOUR
+        timePickerIncrement=datePicker.TIME_PICKER_INCREMENT
+        start=datePicker.RANGE_START
+        end=datePicker.RANGE_END
+        ranges=datePicker.PREDEFINED_RANGES
+        showCustomRangeLabel=datePicker.SHOW_CUSTOM_RANGE_LABEL
+        format=datePicker.UI_DATE_FORMAT
+        serverFormat=datePicker.SERVER_FORMAT
+        applyAction=(action "onRangeSelection")
+      }}
+    </section>
+  
+    <section class="te-content-block__performance-health-wrapper">
+      {{detection-health
+        health=model.detectionHealth
+      }}       
+    </section>
+  </section>
+</section>
+
+{{outlet}}
\ No newline at end of file
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js b/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
index 751a136..69fd822 100644
--- a/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/route.js
@@ -134,6 +134,21 @@ export default Route.extend(AuthenticatedRouteMixin, {
     });
   },
 
+  /**
+   * Ember lifecycle hook. Redirect to the subroute depending on the type of the alert
+   *
+   * @override
+   */
+  redirect() {
+    /**
+     * We will be temporarily redirecting to single-metric-anomalies route for all alerts.
+     * Once the new route is ready for composite anomalies, extract model.alertData.type and
+     * subsequenty navigate to composite-anomalies route if type is 'COMPOSITE_ALERT', else
+     * navigate to single-metric-anomalies route.
+     */
+    this.transitionTo('manage.explore.single-metric-anomalies');
+  },
+
   actions: {
     /**
      * save session url for transition on login
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/controller.js b/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/controller.js
new file mode 100644
index 0000000..d630f31
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/controller.js
@@ -0,0 +1,4 @@
+import Controller from '@ember/controller';
+
+export default Controller.extend({
+});
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/route.js b/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/route.js
new file mode 100644
index 0000000..4c5883b
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/route.js
@@ -0,0 +1,16 @@
+import Route from "@ember/routing/route";
+import AuthenticatedRouteMixin from "ember-simple-auth/mixins/authenticated-route-mixin";
+
+export default Route.extend(AuthenticatedRouteMixin, {
+  /**
+   * Ember Route life hook
+   *
+   * @override
+   *
+   * @return {Object}
+   *   The model for this route
+   */
+  model() {
+    return this.modelFor("manage.explore");
+  }
+});
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/template.hbs b/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/template.hbs
new file mode 100644
index 0000000..113535a
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/single-metric-anomalies/template.hbs
@@ -0,0 +1,20 @@
+<section class="te-page__bottom">
+  <section class="container">
+    {{alert-details
+      isPreviewMode=false
+      alertYaml=model.detectionYaml
+      showDetails=true
+      dataIsCurrent=true
+      alertId=model.alertId
+      alertData=model.alertData
+      metricUrnRoute=model.metricUrn
+      metricUrnListRoute=model.metricUrnList
+      granularity=model.granularity
+      dimensionExploration=model.alertData.dimensionExploration
+      detectionHealth=model.detectionHealth
+      timeWindowSize=model.timeWindowSize
+    }}
+  </section>
+</section>
+
+{{outlet}}
\ No newline at end of file
diff --git a/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs b/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs
index a0599f7..617a080 100644
--- a/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs
+++ b/thirdeye/thirdeye-frontend/app/pods/manage/explore/template.hbs
@@ -1,4 +1,4 @@
-<section class="te-page__top te-search-results {{if isEditModeActive "te-search-results--slim"}}">
+<section class="te-page__top {{if isEditModeActive "te-search-results--slim"}}">
   <div class="container">
     {{#self-serve-alert-yaml-details
       alertData=model.alertData
@@ -15,30 +15,4 @@
   </div>
 </section>
 
-<section class="te-page__bottom">
-  <div class="container">
-    {{#if isLoadError}}
-    <div class="te-alert-page-pending">
-      <img src="{{rootURL}}assets/images/te-alert-error.png"
-        class="te-alert-page-pending__image te-alert-page-pending__image--error" alt="error">
-      <h2 class="te-alert-page-pending__title">Oops, something went wrong</h2>
-      <p class="te-alert-page-pending__text">{{errorText}}</p>
-    </div>
-    {{else}}
-    {{alert-details
-        isPreviewMode=false
-        alertYaml=model.detectionYaml
-        showDetails=true
-        dataIsCurrent=true
-        alertId=model.alertId
-        alertData=model.alertData
-        metricUrnRoute=model.metricUrn
-        metricUrnListRoute=model.metricUrnList
-        granularity=model.granularity
-        dimensionExploration=model.alertData.dimensionExploration
-        detectionHealth=model.detectionHealth
-        timeWindowSize=model.timeWindowSize
-      }}
-    {{/if}}
-  </div>
-</section>
\ No newline at end of file
+{{outlet}}
diff --git a/thirdeye/thirdeye-frontend/app/router.js b/thirdeye/thirdeye-frontend/app/router.js
index 945a302..6a7acc6 100644
--- a/thirdeye/thirdeye-frontend/app/router.js
+++ b/thirdeye/thirdeye-frontend/app/router.js
@@ -26,7 +26,10 @@ Router.map(function() {
     this.route('alerts', function() {
       this.route('index', { path: '/' });
     });
-    this.route('explore', { path: 'explore/:alert_id'});
+    this.route('explore', { path: 'explore/:alert_id'}, function() {
+      this.route('single-metric-anomalies');
+      this.route('composite-anomalies');
+    });
     this.route('yaml', { path: 'yaml/:alert_id' });
   });
 
diff --git a/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss b/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss
index b3c34b4..0541131 100644
--- a/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss
+++ b/thirdeye/thirdeye-frontend/app/styles/shared/_styles.scss
@@ -87,6 +87,11 @@ body {
   }
 }
 
+.te-range-picker {
+  input {
+    border-radius: 20px;
+  }
+}
 .te-icon {
   &__inline-link {
     color: $te-link-blue;
@@ -206,7 +211,6 @@ body {
       width: 600px;
       float: left;
       margin-left: -15px;
-      display: inline-block;
       color: app-shade(black, 7);
     }
 
@@ -240,28 +244,42 @@ body {
   background: white;
   padding: 24px;
 
+  &__date-picker-section {
+    display:flex;
+    flex-direction: row;
+    align-items: center;
+
+    .te-range-picker {
+      margin-left: 10px;
+      flex-basis: 35%;
+
+      display: flex;
+      align-items: center;
+    }
+  }
+
+  &__date-picker-label {
+    margin-bottom: 15px;
+    
+    color: rgba(0, 0, 0, 0.9);
+    font-weight: 500;
+    font-size: 14px;
+  }
+
   &__alert-performance {
-    display: inline-block;
-    width: calc(80% - 20px);
-    margin-right: 10px;
     font-family: "Source Sans Pro", sans-serif;
     background: white;
     padding: 24px;
-    padding-bottom: 100%;
-    margin-bottom: -100%;
+    flex-basis: 75%;
     border-right: 2px solid app-shade(black, 1);
   }
 
   &__detection-health {
-    width: 20%;
-    display: inline-block;
-    float: right;
     margin-left: 10px;
     font-family: "Source Sans Pro", sans-serif;
     background: white;
     padding: 24px;
-    padding-bottom: 100%;
-    margin-bottom: -100%;
+    flex-basis: 25%
   }
 
   &__performance-health-wrapper {
@@ -269,6 +287,7 @@ body {
     border-radius: 5px;
     border: 2px solid app-shade(black, 1);
     background: white;
+    display: flex;
   }
 }
 
@@ -368,6 +387,10 @@ body {
     width: 100%;
     border-top: 1px app-shade(black, 1) solid;
   }
+
+  &__middle {
+    background: white;
+  }
 }
 
 .te-self-serve {
@@ -784,9 +807,6 @@ body {
     }
   }
 
-  &__header {
-  }
-
   &__row {
     display: flex;
     font-size: $te-font-size-small;
diff --git a/thirdeye/thirdeye-frontend/app/utils/date-picker-utils.js b/thirdeye/thirdeye-frontend/app/utils/date-picker-utils.js
new file mode 100644
index 0000000..258b19e
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/utils/date-picker-utils.js
@@ -0,0 +1,66 @@
+import moment from "moment";
+
+const DISPLAY_DATE_FORMAT = "YYYY-MM-DD HH:mm";
+
+const BASE_SPEC = {
+  TIME_PICKER: true,
+  TIME_PICKER_24_HOUR: true,
+  TIME_PICKER_INCREMENT: 5,
+  SHOW_CUSTOM_RANGE_LABEL: false,
+  UI_DATE_FORMAT: "MMM D, YYYY hh:mm a",
+  SERVER_FORMAT: "YYYY-MM-DD HH:mm"
+};
+
+const PREDEFINED_RANGES = {
+  "Last 48 Hours": [
+    moment()
+      .subtract(48, "hour")
+      .startOf("hour"),
+    moment().startOf("hour")
+  ],
+  "Last Week": [
+    moment()
+      .subtract(1, "week")
+      .startOf("day"),
+    moment().startOf("day")
+  ],
+  "Last 30 Days": [
+    moment()
+      .subtract(1, "month")
+      .startOf("day"),
+    moment().startOf("day")
+  ]
+};
+
+/**
+ * Convert the date passed in milliseconds to string format ("YYYY-MM-DD HH:mm")
+ *
+ * @param {Number} date
+ *   Date in milliseconds format
+ *
+ * @return {String}
+ *   The date in "YYYY-MM-DD HH:mm" format
+ */
+const getInitialDate = date => {
+  return moment(date).format(DISPLAY_DATE_FORMAT);
+};
+
+/**
+ * Get the specification to initialize the date-range-picker with.
+ *
+ * @param {Number} startDate
+ *   Start date in milliseconds format
+ * @param {Number} endDate
+ *   End date in milliseconds format
+ *
+ * @return {Object}
+ *   The specification to initialize the date-range-picker
+ */
+export const getDatePickerSpec = (startDate, endDate) => {
+  return {
+    ...BASE_SPEC,
+    PREDEFINED_RANGES: { ...PREDEFINED_RANGES },
+    RANGE_START: getInitialDate(startDate),
+    RANGE_END: getInitialDate(endDate)
+  };
+};
diff --git a/thirdeye/thirdeye-frontend/tests/unit/pods/manage/explore/composite-anomalies/route-test.js b/thirdeye/thirdeye-frontend/tests/unit/pods/manage/explore/composite-anomalies/route-test.js
new file mode 100644
index 0000000..bf6b34c
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/tests/unit/pods/manage/explore/composite-anomalies/route-test.js
@@ -0,0 +1,11 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | manage/explore/composite-anomalies', function(hooks) {
+  setupTest(hooks);
+
+  test('it exists', function(assert) {
+    let route = this.owner.lookup('route:manage/explore/composite-anomalies');
+    assert.ok(route);
+  });
+});
diff --git a/thirdeye/thirdeye-frontend/tests/unit/pods/manage/explore/single-metric-anomalies/route-test.js b/thirdeye/thirdeye-frontend/tests/unit/pods/manage/explore/single-metric-anomalies/route-test.js
new file mode 100644
index 0000000..8708140
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/tests/unit/pods/manage/explore/single-metric-anomalies/route-test.js
@@ -0,0 +1,11 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | manage/explore/single-metric-anomalies', function(hooks) {
+  setupTest(hooks);
+
+  test('it exists', function(assert) {
+    let route = this.owner.lookup('route:manage/explore/single-metric-anomalies');
+    assert.ok(route);
+  });
+});
diff --git a/thirdeye/thirdeye-frontend/tests/unit/utils/date-picker-utils-test.js b/thirdeye/thirdeye-frontend/tests/unit/utils/date-picker-utils-test.js
new file mode 100644
index 0000000..1b09c04
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/tests/unit/utils/date-picker-utils-test.js
@@ -0,0 +1,36 @@
+import { module, test } from "qunit";
+import { getDatePickerSpec } from "thirdeye-frontend/utils/date-picker-utils";
+
+module("Unit | Utility | Date picker utils", function() {
+  test("it returns a the date picker spec correctly", function(assert) {
+    const {
+      TIME_PICKER,
+      TIME_PICKER_24_HOUR,
+      TIME_PICKER_INCREMENT,
+      SHOW_CUSTOM_RANGE_LABEL,
+      UI_DATE_FORMAT,
+      SERVER_FORMAT,
+      RANGE_START,
+      RANGE_END,
+      PREDEFINED_RANGES
+    } = getDatePickerSpec(1602745200000, 1605427200000);
+
+    const predefinedRangesKeys = Object.keys(PREDEFINED_RANGES);
+
+    assert.equal(TIME_PICKER, true);
+    assert.equal(TIME_PICKER_24_HOUR, true);
+    assert.equal(TIME_PICKER_INCREMENT, 5);
+    assert.equal(SHOW_CUSTOM_RANGE_LABEL, false);
+    assert.equal(UI_DATE_FORMAT, "MMM D, YYYY hh:mm a");
+    assert.equal(SERVER_FORMAT, "YYYY-MM-DD HH:mm");
+    assert.ok(RANGE_START.includes("2020-10-15"));
+    assert.ok(RANGE_END.includes("2020-11-15"));
+
+    assert.equal(predefinedRangesKeys.length, 3);
+    assert.deepEqual(predefinedRangesKeys, [
+      "Last 48 Hours",
+      "Last Week",
+      "Last 30 Days"
+    ]);
+  });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org