[GitHub] metron pull request #768: Metron 1123: Add group by option using faceted sea...
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...
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...
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...
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...
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...
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...
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...
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...
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...
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...
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