You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by sa...@apache.org on 2019/04/01 16:43:43 UTC

[metron] branch master updated: METRON-2052 [UI] Changing default query time range to 15 minutes (tiborm via sardell) closes apache/metron#1369

This is an automated email from the ASF dual-hosted git repository.

sardell pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/metron.git


The following commit(s) were added to refs/heads/master by this push:
     new 88d3ca8  METRON-2052 [UI] Changing default query time range to 15 minutes (tiborm via sardell) closes apache/metron#1369
88d3ca8 is described below

commit 88d3ca8a51f7b1ee059df4f1458dbceefd090e15
Author: tiborm <ti...@gmail.com>
AuthorDate: Mon Apr 1 18:35:46 2019 +0200

    METRON-2052 [UI] Changing default query time range to 15 minutes (tiborm via sardell) closes apache/metron#1369
---
 .../alerts-list/alerts-list.component.spec.ts      | 99 ++++++++++++++++++++++
 .../alerts/alerts-list/alerts-list.component.ts    | 35 ++++++--
 .../app/shared/time-range/time-range.component.ts  | 39 ++++++---
 .../metron-alerts/src/app/utils/utils.ts           |  8 +-
 4 files changed, 157 insertions(+), 24 deletions(-)

diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts
new file mode 100644
index 0000000..7adbbe9
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.spec.ts
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * 'License'); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { AlertsListComponent } from './alerts-list.component';
+import { ComponentFixture, async, TestBed } from '@angular/core/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { RouterTestingModule } from '@angular/router/testing';
+import { SearchService } from 'app/service/search.service';
+import { UpdateService } from 'app/service/update.service';
+import { ConfigureTableService } from 'app/service/configure-table.service';
+import { AlertsService } from 'app/service/alerts.service';
+import { ClusterMetaDataService } from 'app/service/cluster-metadata.service';
+import { SaveSearchService } from 'app/service/save-search.service';
+import { MetaAlertService } from 'app/service/meta-alert.service';
+import { GlobalConfigService } from 'app/service/global-config.service';
+import { DialogService } from 'app/service/dialog.service';
+import { Observable } from 'rxjs';
+import { Filter } from 'app/model/filter';
+
+fdescribe('AlertsListComponent', () => {
+
+  let component: AlertsListComponent;
+  let fixture: ComponentFixture<AlertsListComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      schemas: [ NO_ERRORS_SCHEMA ],
+      imports: [
+        RouterTestingModule.withRoutes([]),
+      ],
+      declarations: [
+        AlertsListComponent,
+      ],
+      providers: [
+        { provide: SearchService, useClass: () => { return {} } },
+        { provide: UpdateService, useClass: () => { return {
+          alertChanged$: new Observable(),
+        } } },
+        { provide: ConfigureTableService, useClass: () => { return {
+          getTableMetadata: () => new Observable(),
+          tableChanged$: new Observable(),
+        } } },
+        { provide: AlertsService, useClass: () => { return {} } },
+        { provide: ClusterMetaDataService, useClass: () => { return {
+          getDefaultColumns: () => new Observable(),
+        } } },
+        { provide: SaveSearchService, useClass: () => { return {
+          loadSavedSearch$: new Observable(),
+        } } },
+        { provide: MetaAlertService, useClass: () => { return {
+          alertChanged$: new Observable(),
+        } } },
+        { provide: GlobalConfigService, useClass: () => { return {
+          get: () => new Observable(),
+        } } },
+        { provide: DialogService, useClass: () => { return {} } },
+      ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(AlertsListComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should exist', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should set default query time range', () => {
+    expect(component.selectedTimeRange instanceof Filter).toBeTruthy();
+    expect(component.selectedTimeRange.value).toBe('last-15-minutes');
+  });
+
+  it('default query time range from date should be set', () => {
+    expect(component.selectedTimeRange.dateFilterValue.fromDate).toBeTruthy();
+  });
+
+  it('default query time range to date should be set', () => {
+    expect(component.selectedTimeRange.dateFilterValue.toDate).toBeTruthy();
+  });
+
+});
diff --git a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
index 342f44e..e743359 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
@@ -46,6 +46,7 @@ import {Facets} from '../../model/facets';
 import { GlobalConfigService } from '../../service/global-config.service';
 import { DialogService } from 'app/service/dialog.service';
 import { DialogType } from 'app/model/dialog-type';
+import { Utils } from 'app/utils/utils';
 
 @Component({
   selector: 'app-alerts-list',
@@ -67,7 +68,9 @@ export class AlertsListComponent implements OnInit, OnDestroy {
   lastIsRefreshPausedValue = false;
   isMetaAlertPresentInSelectedAlerts = false;
   timeStampfilterPresent = false;
-  selectedTimeRange = new Filter(TIMESTAMP_FIELD_NAME, ALL_TIME, false);
+
+  readonly DEFAULT_TIME_RANGE = 'last-15-minutes';
+  selectedTimeRange: Filter;
 
   @ViewChild('table') table: ElementRef;
   @ViewChild('dataViewComponent') dataViewComponent: TableViewComponent;
@@ -135,7 +138,8 @@ export class AlertsListComponent implements OnInit, OnDestroy {
   setSelectedTimeRange(filters: Filter[]) {
     filters.forEach(filter => {
       if (filter.field === TIMESTAMP_FIELD_NAME && filter.dateFilterValue) {
-        this.selectedTimeRange = JSON.parse(JSON.stringify(filter));
+        this.selectedTimeRange = filter;
+        this.updateQueryBuilder(filter);
       }
     });
   }
@@ -199,12 +203,20 @@ export class AlertsListComponent implements OnInit, OnDestroy {
         }
       }
     });
+
+    this.setDefaultTimeRange(this.DEFAULT_TIME_RANGE);
     this.getAlertColumnNames(true);
     this.addAlertColChangedListner();
     this.addLoadSavedSearchListner();
     this.addAlertChangedListner();
   }
 
+  private setDefaultTimeRange(timeRangeId: string) {
+    const timeRange = new Filter(TIMESTAMP_FIELD_NAME, timeRangeId, false);
+    timeRange.dateFilterValue = Utils.timeRangeToDateObj(timeRange.value);
+    this.setSelectedTimeRange([timeRange]);
+  }
+
   onClear() {
     this.timeStampfilterPresent = false;
     this.queryBuilder.clearSearch();
@@ -229,7 +241,9 @@ export class AlertsListComponent implements OnInit, OnDestroy {
 
   onSelectedAlertsChange(selectedAlerts) {
     this.selectedAlerts = selectedAlerts;
-    this.isMetaAlertPresentInSelectedAlerts = this.selectedAlerts.some(alert => (alert.source.metron_alert && alert.source.metron_alert.length > 0));
+    this.isMetaAlertPresentInSelectedAlerts = this.selectedAlerts.some(
+      alert => (alert.source.metron_alert && alert.source.metron_alert.length > 0)
+    );
 
     if (selectedAlerts.length > 0) {
       this.pause();
@@ -266,17 +280,20 @@ export class AlertsListComponent implements OnInit, OnDestroy {
 
   onResize() {
     clearTimeout(this.colNumberTimerId);
-    this.colNumberTimerId = setTimeout(() => { this.calcColumnsToDisplay(); }, 500);
+    this.colNumberTimerId = window.setTimeout(() => { this.calcColumnsToDisplay(); }, 500);
   }
 
   onTimeRangeChange(filter: Filter) {
-    if (filter.value === ALL_TIME) {
-      this.queryBuilder.removeFilter(filter.field);
+    this.updateQueryBuilder(filter);
+    this.search();
+  }
+
+  private updateQueryBuilder(timeRangeFilter: Filter) {
+    if (timeRangeFilter.value === ALL_TIME) {
+      this.queryBuilder.removeFilter(timeRangeFilter.field);
     } else {
-      this.queryBuilder.addOrUpdateFilter(filter);
+      this.queryBuilder.addOrUpdateFilter(timeRangeFilter);
     }
-
-    this.search();
   }
 
   prepareColumnData(configuredColumns: ColumnMetadata[], defaultColumns: ColumnMetadata[]) {
diff --git a/metron-interface/metron-alerts/src/app/shared/time-range/time-range.component.ts b/metron-interface/metron-alerts/src/app/shared/time-range/time-range.component.ts
index 2600189..9c3a61f 100644
--- a/metron-interface/metron-alerts/src/app/shared/time-range/time-range.component.ts
+++ b/metron-interface/metron-alerts/src/app/shared/time-range/time-range.component.ts
@@ -15,15 +15,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, OnInit, ViewChild, ElementRef, HostListener, EventEmitter, Output, Input, OnChanges, SimpleChanges} from '@angular/core';
+import {
+  Component,
+  ViewChild,
+  ElementRef,
+  HostListener,
+  EventEmitter,
+  Output,
+  Input,
+  OnChanges,
+  SimpleChanges
+} from '@angular/core';
 import * as moment from 'moment/moment';
 
-import {Filter} from '../../model/filter';
+import { Filter } from '../../model/filter';
 import {
     DEFAULT_TIMESTAMP_FORMAT, CUSTOMM_DATE_RANGE_LABEL,
     TIMESTAMP_FIELD_NAME, ALL_TIME
 } from '../../utils/constants';
-import {DateFilterValue} from '../../model/date-filter-value';
+import { DateFilterValue } from '../../model/date-filter-value';
 
 @Component({
   selector: 'app-time-range',
@@ -35,14 +45,14 @@ export class TimeRangeComponent implements OnChanges {
   fromDateStr = '';
   datePickerFromDate = '';
   datePickerToDate = '';
-  selectedTimeRangeValue = 'All time';
+  selectedTimeRangeValue = 'Last 15 minutes';
 
   @Input() disabled = false;
   @Input() selectedTimeRange: Filter;
   @ViewChild('datePicker') datePicker: ElementRef;
   @Output() timeRangeChange = new EventEmitter<Filter>();
 
-  timeRangeMappingCol1 = {
+  readonly timeRangeMappingCol1 = {
     'Last 7 days':            'last-7-days',
     'Last 30 days':           'last-30-days',
     'Last 60 days':           'last-60-days',
@@ -52,7 +62,7 @@ export class TimeRangeComponent implements OnChanges {
     'Last 2 years':           'last-2-years',
     'Last 5 years':           'last-5-years'
   };
-  timeRangeMappingCol2 = {
+  readonly timeRangeMappingCol2 = {
     'Yesterday':              'yesterday',
     'Day before yesterday':   'day-before-yesterday',
     'This day last week':     'this-day-last-week',
@@ -61,7 +71,7 @@ export class TimeRangeComponent implements OnChanges {
     'Previous year':          'previous-year',
     'All time':               ALL_TIME
   };
-  timeRangeMappingCol3 = {
+  readonly timeRangeMappingCol3 = {
     'Today':                  'today',
     'Today so far':           'today-so-far',
     'This week':              'this-week',
@@ -69,7 +79,7 @@ export class TimeRangeComponent implements OnChanges {
     'This month':             'this-month',
     'This year':              'this-year'
   };
-  timeRangeMappingCol4 = {
+  readonly timeRangeMappingCol4 = {
     'Last 5 minutes':         'last-5-minutes',
     'Last 15 minutes':        'last-15-minutes',
     'Last 30 minutes':        'last-30-minutes',
@@ -90,7 +100,14 @@ export class TimeRangeComponent implements OnChanges {
 
   onSelectedTimeRangeChange() {
     let foundQuickRange = false;
-    let merged = Object.assign({}, this.timeRangeMappingCol1, this.timeRangeMappingCol2, this.timeRangeMappingCol3, this.timeRangeMappingCol4);
+    const merged = Object.assign(
+      {},
+      this.timeRangeMappingCol1,
+      this.timeRangeMappingCol2,
+      this.timeRangeMappingCol3,
+      this.timeRangeMappingCol4
+    );
+
     Object.keys(merged).forEach(key => {
       if (this.selectedTimeRange.value === merged[key]) {
         foundQuickRange = true;
@@ -160,7 +177,7 @@ export class TimeRangeComponent implements OnChanges {
   }
 
   isPikaSelectElement(targetElement: HTMLElement): boolean {
-    while(targetElement) {
+    while (targetElement) {
       if (targetElement.classList.toString().startsWith('pika')){
         return true;
       }
@@ -176,7 +193,7 @@ export class TimeRangeComponent implements OnChanges {
       return;
     }
 
-    if(this.isPikaSelectElement(targetElement)) {
+    if (this.isPikaSelectElement(targetElement)) {
       return;
     }
 
diff --git a/metron-interface/metron-alerts/src/app/utils/utils.ts b/metron-interface/metron-alerts/src/app/utils/utils.ts
index 4eb098a..872d33d 100644
--- a/metron-interface/metron-alerts/src/app/utils/utils.ts
+++ b/metron-interface/metron-alerts/src/app/utils/utils.ts
@@ -25,7 +25,7 @@ import { PcapFilterFormValue } from '../pcap/pcap-filters/pcap-filters.component
 import { FormGroup } from '@angular/forms';
 
 export class Utils {
-  
+
   public static escapeESField(field: string): string {
     return field.replace(/:/g, '\\:');
   }
@@ -45,7 +45,7 @@ export class Utils {
     }
   }
 
-  public static timeRangeToDateObj(range:string) {
+  public static timeRangeToDateObj(range: string): DateFilterValue {
     let timeRangeToDisplayStr = Utils.timeRangeToDisplayStr(range);
     if (timeRangeToDisplayStr != null) {
       let toDate = new Date((timeRangeToDisplayStr.toDate)).getTime();
@@ -60,7 +60,7 @@ export class Utils {
     return null;
   }
 
-  public static parseTimeRange(range:string) {
+  public static parseTimeRange(range: string): { toDate: number, fromDate: number } {
     let parsed = range.replace(/^\(>=/, '')
     .replace(/\)$/, '')
     .replace(/<=/, '').split('AND');
@@ -74,7 +74,7 @@ export class Utils {
     return null;
   }
 
-  public static timeRangeToDisplayStr(range:string) {
+  public static timeRangeToDisplayStr(range: string): { toDate: string, fromDate: string } {
     let toDate = '';
     let fromDate = '';