This is an automated email from the ASF dual-hosted git repository. sardell pushed a commit to branch feature/METRON-1856-parser-aggregation in repository https://gitbox.apache.org/repos/asf/metron.git
The following commit(s) were added to refs/heads/feature/METRON-1856-parser-aggregation by this push: new 423eed6 METRON-2139 Refactoring sensor-parser-config.component and wire NgRx (ruffle1986 via sardell) closes apache/metron#1494 423eed6 is described below commit 423eed6d04f7c82ecf36717c5b19a65c0dffcae5 Author: ruffle1986 <ftamas.m...@gmail.com> AuthorDate: Mon Aug 26 14:12:34 2019 +0200 METRON-2139 Refactoring sensor-parser-config.component and wire NgRx (ruffle1986 via sardell) closes apache/metron#1494 --- .../sensor-parser-config-readonly.component.html | 2 +- .../sensor-parser-config.component.html | 4 +- .../sensor-parser-config.component.spec.ts | 219 +++++++++++---------- .../sensor-parser-config.component.ts | 70 ++++--- .../sensor-parser-latency.pipe.ts} | 15 +- .../sensor-parser-throughput.pipe.ts} | 15 +- .../src/app/sensors/sensors.module.ts | 4 +- .../metron-config/src/tsconfig.spec.json | 1 + 8 files changed, 192 insertions(+), 138 deletions(-) diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html index bd13c1c..d0c3caf 100644 --- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.html @@ -44,7 +44,7 @@ <div *ngIf="item.model == 'kafkaTopic'" class="col-sm-6 px-0 float-left form-value">{{ kafkaTopic[item.value] ? kafkaTopic[item.value] : "-" }}</div> <div *ngIf="item.model == 'topologyStatus'" class="col-sm-6 px-0 float-left form-value">{{ getTopologyStatus(item.value) }}</div> - <div *ngIf="item.model == 'grokStatement' && sensorParserConfigHistory.config.parserClassName === 'org.apache.metron.parsers.GrokParser'" style="border: none"> + <div *ngIf="item.model == 'grokStatement' && sensorParserConfig.parserClassName === 'org.apache.metron.parsers.GrokParser'" style="border: none"> <div class="col-sm-12 form-sub-title">Grok Statement</div> <div id="collapseGrok" class="col-sm-12 float-left form-value panel-collapse collapse"></div> <div class="col-sm-12 float-left form-value grok" [innerHtml]="grokStatement"></div> diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html index b4bdd92..bdb006f 100644 --- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.html @@ -11,7 +11,7 @@ OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> -<metron-config-metron-modal> +<metron-config-metron-modal *ngIf="sensorParserConfig"> <metron-config-sensor-grok [hidden]="!showGrokValidator" [showGrok]="showGrokValidator" [grokStatement]="grokStatement" [(patternLabel)]="patternLabel" @@ -44,7 +44,7 @@ <div class="form-title">{{sensorName}} </div> <i class="fa fa-times float-right main close-button" aria-hidden="true" (click)="goBack()"></i> - <form role="form" [formGroup]="sensorConfigForm"> + <form *ngIf="sensorConfigForm" role="form" [formGroup]="sensorConfigForm"> <div class="form-group"> <label attr.for="sensorName">NAME * </label> <input type="text" class="form-control" name="sensorName" formControlName="sensorName" [(ngModel)]="sensorName" (ngModelChange)="onSetSensorName()" [readonly]="editMode"> diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.spec.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.spec.ts index ff1a812..bb6ed77 100644 --- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.spec.ts +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.spec.ts @@ -16,7 +16,6 @@ * limitations under the License. */ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Inject } from '@angular/core'; import { Observable, throwError } from 'rxjs'; import { Router, ActivatedRoute, Params } from '@angular/router'; import { HttpClient, HttpResponse } from '@angular/common/http'; @@ -31,7 +30,7 @@ import { KafkaService } from '../../service/kafka.service'; import { KafkaTopic } from '../../model/kafka-topic'; import { GrokValidationService } from '../../service/grok-validation.service'; import { MetronAlerts } from '../../shared/metron-alerts'; -import { SensorParserConfig } from '../../model/sensor-parser-config'; +import { ParserConfigModel } from '../../sensors/models/parser-config.model'; import { ParseMessageRequest } from '../../model/parse-message-request'; import { SensorParserContext } from '../../model/sensor-parser-context'; import { AuthenticationService } from '../../service/authentication.service'; @@ -45,8 +44,9 @@ import { of } from 'rxjs'; import { HdfsService } from '../../service/hdfs.service'; import { RestError } from '../../model/rest-error'; import { RiskLevelRule } from '../../model/risk-level-rule'; -import {AppConfigService} from '../../service/app-config.service'; -import {MockAppConfigService} from '../../service/mock.app-config.service'; +import { Store } from '@ngrx/store'; +import { AppConfigService } from '../../service/app-config.service'; +import { MockAppConfigService } from '../../service/mock.app-config.service'; class MockRouter { navigateByUrl(url: string) {} @@ -67,15 +67,15 @@ class MockActivatedRoute { class MockSensorParserConfigService extends SensorParserConfigService { private name: string; - private sensorParserConfig: SensorParserConfig; + private sensorParserConfig: ParserConfigModel; private parsedMessage: any; - private postedSensorParserConfig: SensorParserConfig; + private postedSensorParserConfig: ParserConfigModel; private throwError: boolean; - public post( + public saveConfig( name: string, - sensorParserConfig: SensorParserConfig - ): Observable<SensorParserConfig> { + sensorParserConfig: ParserConfigModel + ): Observable<ParserConfigModel> { if (this.throwError) { let error = new RestError(); error.message = 'SensorParserConfig post error'; @@ -88,14 +88,14 @@ class MockSensorParserConfigService extends SensorParserConfigService { }); } - public get(name: string): Observable<SensorParserConfig> { + public getConfig(name: string): Observable<ParserConfigModel> { return Observable.create(observer => { observer.next(this.sensorParserConfig); observer.complete(); }); } - public getAll(): Observable<{}> { + public getAllConfig(): Observable<{}> { return Observable.create(observer => { let results = {}; results[this.name] = this.sensorParserConfig; @@ -125,7 +125,7 @@ class MockSensorParserConfigService extends SensorParserConfigService { public setSensorParserConfig( name: string, - sensorParserConfig: SensorParserConfig + sensorParserConfig: ParserConfigModel ) { this.name = name; this.sensorParserConfig = sensorParserConfig; @@ -450,71 +450,87 @@ describe('Component: SensorParserConfig', () => { let activatedRoute: MockActivatedRoute; let metronAlerts: MetronAlerts; let router: MockRouter; + let squidSensorParserConfig; + let squidParserMetaInfo; + let squidSensorEnrichmentConfig; + let squidIndexingConfigurations; + let store: Store<any>; - let squidSensorParserConfig: any = { - parserClassName: 'org.apache.metron.parsers.GrokParser', - sensorTopic: 'squid', - parserConfig: { - grokPath: '/apps/metron/patterns/squid', - patternLabel: 'SQUID_DELIMITED', - timestampField: 'timestamp' - }, - fieldTransformations: [ - { - input: [], - output: ['full_hostname', 'domain_without_subdomains', 'hostname'], - transformation: 'STELLAR', - config: { - full_hostname: 'URL_TO_HOST(url)', - domain_without_subdomains: 'DOMAIN_REMOVE_SUBDOMAINS(full_hostname)' + beforeEach(async(() => { + + squidSensorParserConfig = new ParserConfigModel('squid', { + parserClassName: 'org.apache.metron.parsers.GrokParser', + sensorTopic: 'squid', + parserConfig: { + grokPath: '/apps/metron/patterns/squid', + patternLabel: 'SQUID_DELIMITED', + timestampField: 'timestamp' + }, + fieldTransformations: [ + { + input: [], + output: ['full_hostname', 'domain_without_subdomains', 'hostname'], + transformation: 'STELLAR', + config: { + full_hostname: 'URL_TO_HOST(url)', + domain_without_subdomains: 'DOMAIN_REMOVE_SUBDOMAINS(full_hostname)' + } } - } - ] - }; - - let squidSensorEnrichmentConfig = { - enrichment: { - fieldMap: { - geo: ['ip_dst_addr'], - host: ['ip_dst_addr'], - whois: [], - stellar: { config: { group1: {} } } + ] + }); + + squidParserMetaInfo = { + config: squidSensorParserConfig, + }; + + squidSensorEnrichmentConfig = { + enrichment: { + fieldMap: { + geo: ['ip_dst_addr'], + host: ['ip_dst_addr'], + whois: [], + stellar: { config: { group1: {} } } + }, + fieldToTypeMap: {}, + config: {} }, - fieldToTypeMap: {}, - config: {} - }, - threatIntel: { threatIntel: { - fieldMap: { hbaseThreatIntel: ['ip_dst_addr'] }, - fieldToTypeMap: { ip_dst_addr: ['malicious_ip'] } + threatIntel: { + fieldMap: { hbaseThreatIntel: ['ip_dst_addr'] }, + fieldToTypeMap: { ip_dst_addr: ['malicious_ip'] } + } } - } - }; - - let squidIndexingConfigurations = { - hdfs: { - index: 'squid', - batchSize: 5, - enabled: true - }, - elasticsearch: { - index: 'squid', - batchSize: 10, - enabled: true - }, - solr: { - index: 'squid', - batchSize: 1, - enabled: false - } - }; + }; + + squidIndexingConfigurations = { + hdfs: { + index: 'squid', + batchSize: 5, + enabled: true + }, + elasticsearch: { + index: 'squid', + batchSize: 10, + enabled: true + }, + solr: { + index: 'squid', + batchSize: 1, + enabled: false + } + }; - beforeEach(async(() => { TestBed.configureTestingModule({ imports: [SensorParserConfigModule], providers: [ MetronAlerts, { provide: HttpClient }, + { provide: Store, useValue: { + pipe: () => { + return of(squidParserMetaInfo); + }, + dispatch: () => {} + } }, { provide: SensorParserConfigService, useClass: MockSensorParserConfigService @@ -552,6 +568,7 @@ describe('Component: SensorParserConfig', () => { activatedRoute = TestBed.get(ActivatedRoute); metronAlerts = TestBed.get(MetronAlerts); router = TestBed.get(Router); + store = TestBed.get(Store); })); afterEach(() => { @@ -564,21 +581,17 @@ describe('Component: SensorParserConfig', () => { it('should handle ngOnInit', async(() => { spyOn(component, 'init'); - spyOn(component, 'createForms'); - spyOn(component, 'getAvailableParsers'); activatedRoute.setNameForTest('squid'); component.ngOnInit(); expect(component.init).toHaveBeenCalledWith('squid'); - expect(component.createForms).toHaveBeenCalled(); - expect(component.getAvailableParsers).toHaveBeenCalled(); })); it('should createForms', async(() => { component.sensorParserConfig = Object.assign( - new SensorParserConfig(), + new ParserConfigModel('TestConfigId01'), squidSensorParserConfig ); component.createForms(); @@ -611,13 +624,10 @@ describe('Component: SensorParserConfig', () => { ); component.init('new'); - let expectedSensorParserConfig = new SensorParserConfig(); - expectedSensorParserConfig.parserClassName = - 'org.apache.metron.parsers.GrokParser'; + let expectedSensorParserConfig = new ParserConfigModel('new'); + expectedSensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser'; expect(component.sensorParserConfig).toEqual(expectedSensorParserConfig); - expect(component.sensorEnrichmentConfig).toEqual( - new SensorEnrichmentConfig() - ); + expect(component.sensorEnrichmentConfig).toEqual(new SensorEnrichmentConfig()); expect(component.indexingConfigurations).toEqual( new IndexingConfigurations() ); @@ -625,10 +635,7 @@ describe('Component: SensorParserConfig', () => { expect(component.currentSensors).toEqual(['squid']); spyOn(component, 'getKafkaStatus'); - let sensorParserConfig = Object.assign( - new SensorParserConfig(), - squidSensorParserConfig - ); + let sensorParserConfig = squidSensorParserConfig.clone({ sensorTopic: 'squid' }); sensorParserConfigService.setSensorParserConfig( 'squid', sensorParserConfig @@ -647,9 +654,7 @@ describe('Component: SensorParserConfig', () => { ); component.init('squid'); - expect(component.sensorParserConfig).toEqual( - Object.assign(new SensorParserConfig(), squidSensorParserConfig) - ); + expect(component.sensorParserConfig).toEqual(squidSensorParserConfig); expect(component.sensorNameValid).toEqual(true); expect(component.getKafkaStatus).toHaveBeenCalled(); expect(component.showAdvancedParserConfiguration).toEqual(true); @@ -662,13 +667,17 @@ describe('Component: SensorParserConfig', () => { Object.assign(new IndexingConfigurations(), squidIndexingConfigurations) ); - component.sensorParserConfig.parserConfig['grokPath'] = '/patterns/squid'; + component.sensorParserConfig.parserConfig.grokPath = '/patterns/squid'; hdfsService.setContents('/patterns/squid', null); grokValidationService.setContents( '/patterns/squid', 'SQUID grok statement from classpath' ); + store.pipe = () => { + return of({ config: component.sensorParserConfig }); + } + component.init('squid'); expect(component.grokStatement).toEqual( 'SQUID grok statement from classpath' @@ -695,11 +704,15 @@ describe('Component: SensorParserConfig', () => { 'Could not find grok statement in HDFS or classpath at /patterns/squid' ); - sensorParserConfig = new SensorParserConfig(); + sensorParserConfig = new ParserConfigModel('bro'); sensorParserConfig.sensorTopic = 'bro'; sensorParserConfigService.setSensorParserConfig('bro', sensorParserConfig); component.showAdvancedParserConfiguration = false; + store.pipe = () => { + return of({ config: sensorParserConfig }); + } + component.init('bro'); expect(component.showAdvancedParserConfiguration).toEqual(false); })); @@ -714,6 +727,8 @@ describe('Component: SensorParserConfig', () => { it('should handle onSetKafkaTopic', async(() => { spyOn(component, 'getKafkaStatus'); + component.init('new'); + component.onSetKafkaTopic(); expect(component.getKafkaStatus).not.toHaveBeenCalled(); @@ -782,6 +797,8 @@ describe('Component: SensorParserConfig', () => { it('should handle onParserTypeChange', async(() => { spyOn(component, 'hidePane'); + component.init('new'); + component.onParserTypeChange(); expect(component.hidePane).not.toHaveBeenCalled(); @@ -816,8 +833,7 @@ describe('Component: SensorParserConfig', () => { expect(component.isConfigValid()).toEqual(true); - component.sensorParserConfig.parserClassName = - 'org.apache.metron.parsers.GrokParser'; + component.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser'; expect(component.isConfigValid()).toEqual(false); component.grokStatement = 'grok statement'; @@ -825,6 +841,8 @@ describe('Component: SensorParserConfig', () => { })); it('should getKafkaStatus', async(() => { + component.init('bro'); + component.getKafkaStatus(); expect(component.currentKafkaStatus).toEqual(null); @@ -846,6 +864,10 @@ describe('Component: SensorParserConfig', () => { })); it('should getTransforms', async(() => { + component.init('bro'); + + component.sensorParserConfig.fieldTransformations = []; + expect(component.getTransforms()).toEqual('0 Transformations Applied'); component.sensorParserConfig.fieldTransformations.push( @@ -859,6 +881,8 @@ describe('Component: SensorParserConfig', () => { })); it('should handle onSaveGrokStatement', async(() => { + component.init('bro'); + component.sensorName = 'squid'; component.onSaveGrokStatement('grok statement'); @@ -881,6 +905,8 @@ describe('Component: SensorParserConfig', () => { })); it('should onSavePatternLabel', async(() => { + component.init('bro'); + component.onSavePatternLabel('PATTERN_LABEL'); expect(component.patternLabel).toEqual('PATTERN_LABEL'); expect(component.sensorParserConfig.parserConfig['patternLabel']).toEqual( @@ -897,13 +923,15 @@ describe('Component: SensorParserConfig', () => { })); it('should save sensor configuration', async(() => { + component.init('new'); + let fieldTransformer = Object.assign(new FieldTransformer(), { input: [], output: ['url_host'], transformation: 'MTL', config: { url_host: 'TO_LOWER(URL_TO_HOST(url))' } }); - let sensorParserConfigSave: SensorParserConfig = new SensorParserConfig(); + let sensorParserConfigSave: ParserConfigModel = new ParserConfigModel('whatever'); sensorParserConfigSave.sensorTopic = 'squid'; sensorParserConfigSave.parserClassName = 'org.apache.metron.parsers.GrokParser'; @@ -917,6 +945,7 @@ describe('Component: SensorParserConfig', () => { spyOn(metronAlerts, 'showErrorMessage'); component.sensorParserConfig.sensorTopic = 'squid'; + component.sensorName = 'whatever'; component.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser'; component.sensorParserConfig.parserConfig['grokPath'] = @@ -982,6 +1011,8 @@ describe('Component: SensorParserConfig', () => { })); it('should getTransformationCount', async(() => { + component.init('new'); + let transforms = [ Object.assign(new FieldTransformer(), { input: ['method'], @@ -1103,16 +1134,6 @@ describe('Component: SensorParserConfig', () => { expect(component.patternLabel).toEqual('PATTERN_LABEL'); })); - it('should handle onRawJsonChanged', async(() => { - spyOn(component.sensorFieldSchema, 'createFieldSchemaRows'); - - component.onRawJsonChanged(); - - expect( - component.sensorFieldSchema.createFieldSchemaRows - ).toHaveBeenCalled(); - })); - it('should handle onAdvancedConfigFormClose', async(() => { component.onAdvancedConfigFormClose(); diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts index bb59de5..ca3a451 100644 --- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config/sensor-parser-config.component.ts @@ -17,7 +17,7 @@ */ import { Component, OnInit, ViewChild } from '@angular/core'; import { FormGroup, Validators, FormControl } from '@angular/forms'; -import { SensorParserConfig } from '../../model/sensor-parser-config'; +import { ParserConfigModel } from '../models/parser-config.model'; import { SensorParserConfigService } from '../../service/sensor-parser-config.service'; import { Router, ActivatedRoute } from '@angular/router'; import { MetronAlerts } from '../../shared/metron-alerts'; @@ -32,6 +32,12 @@ import { IndexingConfigurations } from '../../model/sensor-indexing-config'; import { RestError } from '../../model/rest-error'; import { HdfsService } from '../../service/hdfs.service'; import { GrokValidationService } from '../../service/grok-validation.service'; +import { SensorState } from '../reducers'; +import { Store, select } from '@ngrx/store'; +import { ParserMetaInfoModel } from '../models/parser-meta-info.model'; +import { filter } from 'rxjs/operators'; +import * as fromReducers from '../reducers'; +import * as fromActions from '../actions'; export enum Pane { GROK, @@ -57,7 +63,7 @@ export class SensorParserConfigComponent implements OnInit { transformsValidationForm: FormGroup; sensorName: string = ''; - sensorParserConfig: SensorParserConfig = new SensorParserConfig(); + sensorParserConfig: ParserConfigModel = new ParserConfigModel(''); sensorEnrichmentConfig: SensorEnrichmentConfig = new SensorEnrichmentConfig(); indexingConfigurations: IndexingConfigurations = new IndexingConfigurations(); @@ -109,26 +115,39 @@ export class SensorParserConfigComponent implements OnInit { private grokValidationService: GrokValidationService, private router: Router, private kafkaService: KafkaService, - private hdfsService: HdfsService - ) { - this.sensorParserConfig.parserConfig = {}; + private hdfsService: HdfsService, + private store: Store<SensorState>, + ) {} + + ngOnInit() { + this.route.params.subscribe(params => { + const id = params['id']; + this.init(id); + }); } init(id: string): void { if (id !== 'new') { this.editMode = true; this.sensorName = id; - this.sensorParserConfigService - .get(id) - .subscribe((results: SensorParserConfig) => { - this.sensorParserConfig = results; + this.store.pipe(select(fromReducers.getParserConfig(), { id })) + .subscribe((parserConfig: ParserMetaInfoModel) => { + + if (!parserConfig) { + return; + } + + this.sensorParserConfig = (parserConfig.config as ParserConfigModel).clone(); this.sensorNameValid = true; this.getKafkaStatus(); + this.createForms(); + this.getAvailableParsers(); + if (Object.keys(this.sensorParserConfig.parserConfig).length > 0) { this.showAdvancedParserConfiguration = true; } if (this.isGrokParser(this.sensorParserConfig)) { - let path = this.sensorParserConfig.parserConfig['grokPath']; + let path = this.sensorParserConfig.parserConfig.grokPath; if (path) { this.hdfsService.read(path).subscribe( contents => { @@ -180,24 +199,18 @@ export class SensorParserConfigComponent implements OnInit { } ); } else { - this.sensorParserConfig = new SensorParserConfig(); + // in case of new parser config + this.sensorParserConfig = new ParserConfigModel(id || ''); this.sensorParserConfig.parserClassName = 'org.apache.metron.parsers.GrokParser'; - this.sensorParserConfigService.getAll().subscribe((results: {}) => { + this.sensorParserConfigService.getAllConfig().subscribe((results: {}) => { this.currentSensors = Object.keys(results); }); + this.createForms(); + this.getAvailableParsers(); } } - ngOnInit() { - this.route.params.subscribe(params => { - let id = params['id']; - this.init(id); - }); - this.createForms(); - this.getAvailableParsers(); - } - createSensorConfigForm(): FormGroup { let group: any = {}; @@ -274,7 +287,7 @@ export class SensorParserConfigComponent implements OnInit { createForms() { this.sensorConfigForm = this.createSensorConfigForm(); this.transformsValidationForm = this.createTransformsValidationForm(); - if (Object.keys(this.sensorParserConfig.parserConfig).length > 0) { + if (Object.keys(this.sensorParserConfig && this.sensorParserConfig.parserConfig).length > 0) { this.showAdvancedParserConfiguration = true; } } @@ -398,6 +411,7 @@ export class SensorParserConfigComponent implements OnInit { } onSave() { + if (!this.indexingConfigurations.hdfs.index) { this.indexingConfigurations.hdfs.index = this.sensorName; } @@ -407,8 +421,16 @@ export class SensorParserConfigComponent implements OnInit { if (!this.indexingConfigurations.solr.index) { this.indexingConfigurations.solr.index = this.sensorName; } + + let sensorParserConfigToSave = this.sensorParserConfig.clone({ id: this.sensorName }); + if (this.editMode) { + this.store.dispatch(new fromActions.UpdateParserConfig(sensorParserConfigToSave)); + } else { + this.store.dispatch(new fromActions.AddParserConfig(sensorParserConfigToSave)); + } + this.sensorParserConfigService - .post(this.sensorName, this.sensorParserConfig) + .saveConfig(this.sensorName, sensorParserConfigToSave) .subscribe( sensorParserConfig => { if (this.isGrokParser(sensorParserConfig)) { @@ -463,7 +485,7 @@ export class SensorParserConfigComponent implements OnInit { ); } - isGrokParser(sensorParserConfig: SensorParserConfig): boolean { + isGrokParser(sensorParserConfig: ParserConfigModel): boolean { if (sensorParserConfig && sensorParserConfig.parserClassName) { return ( sensorParserConfig.parserClassName === diff --git a/metron-interface/metron-config/src/app/sensors/effects/index.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-list/sensor-parser-latency.pipe.ts similarity index 68% copy from metron-interface/metron-config/src/app/sensors/effects/index.ts copy to metron-interface/metron-config/src/app/sensors/sensor-parser-list/sensor-parser-latency.pipe.ts index 8f6ad93..e54e3a3 100644 --- a/metron-interface/metron-config/src/app/sensors/effects/index.ts +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-list/sensor-parser-latency.pipe.ts @@ -15,9 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { Pipe, PipeTransform } from '@angular/core'; +import { TopologyStatus } from '../../model/topology-status'; - import { SensorsEffects } from './sensors.effects'; - - export * from './sensors.effects'; - - export const effects = [ SensorsEffects ]; +@Pipe({ name: 'latency' }) +export class SensorParserLatencyPipe implements PipeTransform { + transform(status: TopologyStatus): string { + return status && status.status === 'ACTIVE' && status.throughput != null + ? (status.latency + 'ms') + : '-'; + } +} diff --git a/metron-interface/metron-config/src/app/sensors/effects/index.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-list/sensor-parser-throughput.pipe.ts similarity index 66% rename from metron-interface/metron-config/src/app/sensors/effects/index.ts rename to metron-interface/metron-config/src/app/sensors/sensor-parser-list/sensor-parser-throughput.pipe.ts index 8f6ad93..b3f3cf0 100644 --- a/metron-interface/metron-config/src/app/sensors/effects/index.ts +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-list/sensor-parser-throughput.pipe.ts @@ -15,9 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { Pipe, PipeTransform } from '@angular/core'; +import { TopologyStatus } from '../../model/topology-status'; - import { SensorsEffects } from './sensors.effects'; - - export * from './sensors.effects'; - - export const effects = [ SensorsEffects ]; +@Pipe({ name: 'throughput' }) +export class SensorParserThroughputPipe implements PipeTransform { + transform(status: TopologyStatus): string { + return status && status.status === 'ACTIVE' && status.throughput != null + ? (Math.round(status.throughput * 100) / 100) + 'kb/s' + : '-'; + } +} diff --git a/metron-interface/metron-config/src/app/sensors/sensors.module.ts b/metron-interface/metron-config/src/app/sensors/sensors.module.ts index 929c0b5..964d350 100644 --- a/metron-interface/metron-config/src/app/sensors/sensors.module.ts +++ b/metron-interface/metron-config/src/app/sensors/sensors.module.ts @@ -31,7 +31,7 @@ import { SensorParserConfigService } from '../service/sensor-parser-config.servi import { KafkaService } from '../service/kafka.service'; import { StormService } from '../service/storm.service'; import { EffectsModule } from '@ngrx/effects'; -import { effects } from './effects'; +import { SensorsEffects } from './effects/sensors.effects'; import { StoreModule } from '@ngrx/store'; import { reducers } from './reducers'; @@ -41,7 +41,7 @@ import { reducers } from './reducers'; SensorParserConfigReadonlyModule, SensorParserConfigModule, SensorParserAggregateSidebarModule, - EffectsModule.forFeature(effects), + EffectsModule.forFeature([SensorsEffects]), StoreModule.forFeature('sensors', reducers), ], declarations: [], diff --git a/metron-interface/metron-config/src/tsconfig.spec.json b/metron-interface/metron-config/src/tsconfig.spec.json index eb43ad2..5112ba4 100644 --- a/metron-interface/metron-config/src/tsconfig.spec.json +++ b/metron-interface/metron-config/src/tsconfig.spec.json @@ -4,6 +4,7 @@ "outDir": "../out-tsc/spec", "module": "commonjs", "target": "es5", + "sourceMap": true, "baseUrl": "", "types": [ "jquery",