[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-13 Thread nickwallen
Github user nickwallen commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r144644294
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

Yes, that makes sense to me. @merrimanr 


---


[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-13 Thread merrimanr
Github user merrimanr commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r144639257
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

I believe this issue is similar to 
https://github.com/apache/metron/pull/768#issuecomment-335281376 and should be 
resolved in the same follow on PR.  Do you agree @nickwallen?


---


[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-12 Thread nickwallen
Github user nickwallen commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r144395087
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

I am also noticing another issue with the group header counts that may or 
may not be related.  

In this example, I am grouping by 'source:type' then 'host'.  Since 'host' 
is specific to bro, there should be no alerts under the "snort" group.  If I 
expand the Snort group, I correctly see no alerts. 

[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-12 Thread nickwallen
Github user nickwallen commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r144387064
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

Actually, I spoke too soon.  @iraghumitra Your fix works great for a single 
group. But if you are grouping by multiple fields, we still get in a state 
where the group headers are showing stale data.  

In this screen shot, I am grouping by source-type, ip_src_addr, then 
country.  
* The count 

[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-12 Thread nickwallen
Github user nickwallen commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r144381219
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

I confirmed manually that the latest does indeed fix this issue.

@merrimanr does have a good point.  A quick unit test of this would be 
great.


---


[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-10 Thread iraghumitra
Github user iraghumitra commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r143715850
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

@nickwallen that's a really nice catch, fixed it


---


[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-09 Thread nickwallen
Github user nickwallen commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r143565157
  
--- Diff: 
metron-interface/metron-alerts/src/app/alerts/alerts-list/tree-view/tree-view.component.ts
 ---
@@ -0,0 +1,319 @@
+/**
+ * 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 { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {Router} from '@angular/router';
+import {Subscription} from 'rxjs/Rx';
+
+import {TableViewComponent} from '../table-view/table-view.component';
+import {SearchResponse} from '../../../model/search-response';
+import {SearchService} from '../../../service/search.service';
+import {TreeGroupData, TreeAlertsSubscription} from './tree-group-data';
+import {GroupResponse} from '../../../model/group-response';
+import {GroupResult} from '../../../model/group-result';
+import {Group} from '../../../model/group';
+import {SortField} from '../../../model/sort-field';
+import {Sort} from '../../../utils/enums';
+import {MetronDialogBox, DialogType} from 
'../../../shared/metron-dialog-box';
+import {ElasticsearchUtils} from '../../../utils/elasticsearch-utils';
+import {SearchRequest} from '../../../model/search-request';
+
+@Component({
+  selector: 'app-tree-view',
+  templateUrl: './tree-view.component.html',
+  styleUrls: ['./tree-view.component.scss']
+})
+
+export class TreeViewComponent extends TableViewComponent implements 
OnChanges {
+
+  groupByFields: string[] = [];
+  topGroups: TreeGroupData[] = [];
+  groupResponse: GroupResponse = new GroupResponse();
+  treeGroupSubscriptionMap: {[key: string]: TreeAlertsSubscription } = {};
+
+  constructor(router: Router,
+  searchService: SearchService,
+  metronDialogBox: MetronDialogBox) {
+super(router, searchService, metronDialogBox);
+  }
+
+  collapseGroup(groupArray: TreeGroupData[], level: number, index: number) 
{
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level > (level)) {
+groupArray[i].show = false;
+groupArray[i].expand = false;
+  } else {
+break;
+  }
+}
+  }
+
+  createQuery(selectedGroup: TreeGroupData) {
+let searchQuery = this.queryBuilder.generateSelect();
+let groupQery = Object.keys(selectedGroup.groupQueryMap).map(key => {
+  return key.replace(/:/g, '\\:') +
+  ':' +
+  String(selectedGroup.groupQueryMap[key])
+  .replace(/[\*\+\-=~><\"\?^\${}\(\)\:\!\/[\]\\\s]/g, '\\$&') // 
replace single  special characters
+  .replace(/\|\|/g, '\\||') // replace ||
+  .replace(/\&\&/g, '\\&&'); // replace &&
+}).join(' AND ');
+
+groupQery += searchQuery === '*' ? '' : (' AND ' + searchQuery);
+return groupQery;
+  }
+
+  expandGroup(groupArray: TreeGroupData[], level: number, index: number) {
+for (let i = index + 1; i < groupArray.length; i++) {
+  if (groupArray[i].level === (level + 1)) {
+groupArray[i].show = true;
+  } else {
+break;
+  }
+}
+  }
+
+  getAlerts(selectedGroup: TreeGroupData): Subscription {
+let searchRequest = new SearchRequest();
+searchRequest.query = this.createQuery(selectedGroup);
+searchRequest.from = selectedGroup.pagingData.from;
+searchRequest.size = selectedGroup.pagingData.size;
+searchRequest.sort = selectedGroup.sortField ? 
[selectedGroup.sortField] : [];
+
+return this.searchGroup(selectedGroup, searchRequest);
--- End diff --

@iraghumitra I noticed that when grouping there are cases when the two 
locations where we display total counts will differ.  See the attached 
screenshots.  I underlined in yellow the counts that I am talking about.

![screen shot 2017-10-09 at 3 26 49 

[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-04 Thread iraghumitra
Github user iraghumitra commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r142671246
  
--- Diff: 
metron-interface/metron-alerts/e2e/alerts-list/tree-view/tree-view.e2e-spec.ts 
---
@@ -0,0 +1,183 @@
+/// 
+/**
+ * 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 {customMatchers} from  '../../matchers/custom-matchers';
+import {LoginPage} from '../../login/login.po';
+import {TreeViewPage} from './tree-view.po';
+import {loadTestData, deleteTestData} from '../../utils/e2e_util';
+import {MetronAlertsPage} from '../alerts-list.po';
+
+describe('metron-alerts tree view', function () {
+  let page: TreeViewPage;
+  let listPage: MetronAlertsPage;
+  let loginPage: LoginPage;
+
+  beforeAll(() => {
+loadTestData();
+loginPage = new LoginPage();
+page = new TreeViewPage();
+listPage = new MetronAlertsPage();
+loginPage.login();
+page.navigateToAlertsList();
+  });
+
+  afterAll(() => {
+loginPage.logout();
+deleteTestData();
+  });
+
+  beforeEach(() => {
+jasmine.addMatchers(customMatchers);
+  });
+
+  it('should have all group by elements', () => {
+let groupByItems = {
+  'source:type': '1',
+  'ip_dst_addr': '8',
+  'host': '9',
+  'enrichm...:country': '3',
+  'ip_src_addr': '2'
+};
+
expect(page.getGroupByCount()).toEqualBcoz(Object.keys(groupByItems).length, '5 
Group By Elements should be present');
+
expect(page.getGroupByItemNames()).toEqualBcoz(Object.keys(groupByItems), 
'Group By Elements names should be present');
+
expect(page.getGroupByItemCounts()).toEqualBcoz(Object.keys(groupByItems).map(key
 => groupByItems[key]),
+'5 Group By Elements 
values should be present');
+  });
+
+  it('should have group details for single group by', () => {
+let dashRowValues = ['0', 'alerts_ui_e2e', 'ALERTS', '169'];
+let row1_page1 = ['-', 'dcda4423-7...0962fafc47', '2017-09-13 
17:59:32', 'alerts_ui_e2e',
+  '192.168.138.158', 'US', '72.34.49.86', 'comarksecurity.com', 'NEW', 
''];
+let row1_page2 = ['-', '07b29c29-9...ff19eaa888', '2017-09-13 
17:59:37', 'alerts_ui_e2e',
+  '192.168.138.158', 'FR', '62.75.195.236', '62.75.195.236', 'NEW', 
''];
+
+page.selectGroup('source:type');
+expect(page.getActiveGroups()).toEqualBcoz(['source:type'], 'only 
source type group should be selected');
+
expect(page.getDashGroupValues('alerts_ui_e2e')).toEqualBcoz(dashRowValues, 
'Dash Group Values should be present');
+
+page.expandDashGroup('alerts_ui_e2e');
+expect(page.getDashGroupTableValuesForRow('alerts_ui_e2e', 
0)).toEqualBcoz(row1_page1, 'Dash Group Values should be present');
+
+page.clickOnNextPage('alerts_ui_e2e');
+expect(page.getTableValuesByRowId('alerts_ui_e2e', 0, 
'FR')).toEqualBcoz(row1_page2, 'Dash Group Values should be present');
+
+page.unGroup();
+expect(page.getActiveGroups()).toEqualBcoz([], 'no groups should be 
selected');
+  });
+
+  it('should have group details for multiple group by', () => {
+
+let dashRow_runLoveUs = {
+  'dashRow': ['0', 'runlove.us', 'ALERTS', '13'],
+  'firstSubGroup': '0 US (13)',
+  'firstSubGroupIdCol': ['9a969c64-b...001cb011a3', 
'a651f7c3-1...a97d4966c9', 'afc36901-3...d931231ab2',
+'d860ac35-1...f9e282d571', '04a5c3d0-9...af17c06fbc']
+};
+
+let dashRow_62_75_195_236 = {
+  'dashRow': ['0', '62.75.195.236', 'ALERTS', '18'],
+  'firstSubGroup': '0 FR (18)',
+  'firstSubGroupIdCol': ['07b29c29-9...ff19eaa888', 
'7cd91565-1...de5be54a6e', 'ca5bde58-a...f3a88d2df4',
+'5d6faf83-8...b88a407647', 'e2883424-f...79bb8b0606']
+};
+
+page.selectGroup('host');
+page.selectGroup('enrichments:geo:ip_dst_addr:country');
+

[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-03 Thread merrimanr
Github user merrimanr commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r142454390
  
--- Diff: 
metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertCreateResponse.java
 ---
@@ -28,4 +28,4 @@ public boolean isCreated() {
   public void setCreated(boolean created) {
 this.created = created;
   }
-}
+}
--- End diff --

Was this intentional?


---


[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-10-03 Thread merrimanr
Github user merrimanr commented on a diff in the pull request:

https://github.com/apache/metron/pull/768#discussion_r142454353
  
--- Diff: 
metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/MetaAlertStatus.java
 ---
@@ -31,4 +31,4 @@
   public String getStatusString() {
 return statusString;
   }
-}
+}
--- End diff --

Was this intentional?


---


[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...

2017-09-21 Thread iraghumitra
GitHub user iraghumitra opened a pull request:

https://github.com/apache/metron/pull/768

Metron 1123: Add group by option using faceted search capabilities of 
metron-rest-api

## Contributor Comments
This PR extends the Metron Alerts GUI capabilities to do group by on Alerts 
Data

The PR is on top of METRON-1189

The group by buttons appear on top of the table. When user selects a group, 
the table view changes to a tree view with the values of the groups as the root 
of the tree. The individual alerts would be shown as the leaf nodes of the tree.

Tree view has all the following features

- Search will search through all the groups
- Users can click on the data  inside the table to search
- Users can select and table inside tree to view the details
- Users can escalate the alerts from the table inside the tree
- Tree view is refreshed automatically depending on the polling setting in 
the settings
- A cumulative score and number of alerts  in a group is shown next to 
group name
- Table inside a group can be paginated
- The column names for the alerts table in the tree can be configured via 
configure column pane

The table config settings is moved next to settings on the GUI as it makes 
more meaning there.


![image](https://user-images.githubusercontent.com/15019012/30694092-29135ce4-9ef0-11e7-88d4-06fee02040bb.png)

![image](https://user-images.githubusercontent.com/15019012/30694106-436d487a-9ef0-11e7-9f76-56b49ebd8c89.png)

![image](https://user-images.githubusercontent.com/15019012/30694113-4c7b8ad0-9ef0-11e7-9a58-5c7988f71430.png)

## Testing  

E2E test cases are available to test groups functionality. From root of the 
project 

```
cd metron-interface/metron-alerts
sh ./scripts/start-server-for-e2e.sh
```

In othere shell run the test cases

```
npm run e2e
```

All the features listed in contributor comments can be verified manually 


## Pull Request Checklist

Thank you for submitting a contribution to Apache Metron.  
Please refer to our [Development 
Guidelines](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=61332235)
 for the complete guide to follow for contributions.  
Please refer also to our [Build Verification 
Guidelines](https://cwiki.apache.org/confluence/display/METRON/Verifying+Builds?show-miniview)
 for complete smoke testing guides.  


In order to streamline the review of the contribution we ask you follow 
these guidelines and ask you to double check the following:

### For all changes:
- [x] Is there a JIRA ticket associated with this PR? If not one needs to 
be created at [Metron 
Jira](https://issues.apache.org/jira/browse/METRON/?selectedTab=com.atlassian.jira.jira-projects-plugin:summary-panel).
 
- [x] Does your PR title start with METRON- where  is the JIRA 
number you are trying to resolve? Pay particular attention to the hyphen "-" 
character.
- [x] Has your PR been rebased against the latest commit within the target 
branch (typically master)?


### For code changes:
- [x] Have you included steps to reproduce the behavior or problem that is 
being changed or addressed?
- [x] Have you included steps or a guide to how the change may be verified 
and tested manually?
- [x] Have you ensured that the full suite of tests and checks have been 
executed in the root metron folder via:
  ```
  mvn -q clean integration-test install && build_utils/verify_licenses.sh 
  ```

- [x] Have you written or updated unit tests and or integration tests to 
verify your changes?
- [x] If adding new dependencies to the code, are these dependencies 
licensed in a way that is compatible for inclusion under [ASF 
2.0](http://www.apache.org/legal/resolved.html#category-a)? 
- [x] Have you verified the basic functionality of the build by building 
and running locally with Vagrant full-dev environment or the equivalent?

### For documentation related changes:
- [x] Have you ensured that format looks appropriate for the output in 
which it is rendered by building and verifying the site-book? If not then run 
the following commands and the verify changes via 
`site-book/target/site/index.html`:

  ```
  cd site-book
  mvn site
  ```

 Note:
Please ensure that once the PR is submitted, you check travis-ci for build 
issues and submit an update to your PR as soon as possible.
It is also recommended that [travis-ci](https://travis-ci.org) is set up 
for your personal repository such that your branches are built there before 
submitting a pull request.


You can merge this pull request into a Git repository by running:

$ git pull https://github.com/iraghumitra/incubator-metron METRON-1123

Alternatively you can review and apply these