You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2017/11/20 12:07:20 UTC
ambari git commit: AMBARI-22477 Log Search UI: implement access logs
table. (ababiichuk)
Repository: ambari
Updated Branches:
refs/heads/trunk 786d4b633 -> cc535c841
AMBARI-22477 Log Search UI: implement access logs table. (ababiichuk)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/cc535c84
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/cc535c84
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/cc535c84
Branch: refs/heads/trunk
Commit: cc535c841f28ea50cf659ada8e573e84141146ac
Parents: 786d4b6
Author: ababiichuk <ab...@hortonworks.com>
Authored: Mon Nov 20 13:33:47 2017 +0200
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Mon Nov 20 13:33:47 2017 +0200
----------------------------------------------------------------------
.../ambari-logsearch-web/src/app/app.module.ts | 6 +-
.../components/logs-table-component.spec.ts | 61 +++++++
.../classes/components/logs-table-component.ts | 51 ++++++
.../src/app/classes/models/audit-log.ts | 2 +-
.../audit-logs-table.component.html | 54 +++++++
.../audit-logs-table.component.less | 21 +++
.../audit-logs-table.component.spec.ts | 157 +++++++++++++++++++
.../audit-logs-table.component.ts | 55 +++++++
.../filters-panel/filters-panel.component.ts | 2 +-
.../logs-container.component.html | 15 +-
.../logs-container/logs-container.component.ts | 62 ++------
.../logs-list/logs-list.component.html | 72 ---------
.../logs-list/logs-list.component.less | 97 ------------
.../logs-list/logs-list.component.spec.ts | 110 -------------
.../components/logs-list/logs-list.component.ts | 151 ------------------
.../service-logs-table.component.html | 76 +++++++++
.../service-logs-table.component.less | 97 ++++++++++++
.../service-logs-table.component.spec.ts | 126 +++++++++++++++
.../service-logs-table.component.ts | 135 ++++++++++++++++
.../ambari-logsearch-web/src/app/mock-data.ts | 4 +-
.../src/app/services/auth.service.spec.ts | 2 +-
.../src/app/services/logs-container.service.ts | 95 +++++++++--
.../src/app/services/mock-api-data.service.ts | 22 +++
23 files changed, 970 insertions(+), 503 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
index 805f8e2..5e43582 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts
@@ -67,7 +67,6 @@ import {DropdownListComponent} from '@app/components/dropdown-list/dropdown-list
import {FilterButtonComponent} from '@app/components/filter-button/filter-button.component';
import {AccordionPanelComponent} from '@app/components/accordion-panel/accordion-panel.component';
import {CollapsiblePanelComponent} from '@app/components/collapsible-panel/collapsible-panel.component';
-import {LogsListComponent} from '@app/components/logs-list/logs-list.component';
import {LogMessageComponent} from '@app/components/log-message/log-message.component';
import {LogLevelComponent} from '@app/components/log-level/log-level.component';
import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component';
@@ -85,6 +84,8 @@ import {DatePickerComponent} from '@app/components/date-picker/date-picker.compo
import {LogContextComponent} from '@app/components/log-context/log-context.component';
import {LogFileEntryComponent} from '@app/components/log-file-entry/log-file-entry.component';
import {TabsComponent} from '@app/components/tabs/tabs.component';
+import {ServiceLogsTableComponent} from '@app/components/service-logs-table/service-logs-table.component';
+import {AuditLogsTableComponent} from '@app/components/audit-logs-table/audit-logs-table.component';
import {TimeZoneAbbrPipe} from '@app/pipes/timezone-abbr.pipe';
import {TimerSecondsPipe} from '@app/pipes/timer-seconds.pipe';
@@ -122,7 +123,6 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
FilterButtonComponent,
AccordionPanelComponent,
CollapsiblePanelComponent,
- LogsListComponent,
LogLevelComponent,
LogMessageComponent,
DropdownButtonComponent,
@@ -140,6 +140,8 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
LogContextComponent,
LogFileEntryComponent,
TabsComponent,
+ ServiceLogsTableComponent,
+ AuditLogsTableComponent,
TimeZoneAbbrPipe,
TimerSecondsPipe
],
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.spec.ts
new file mode 100644
index 0000000..05f80a7
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.spec.ts
@@ -0,0 +1,61 @@
+/**
+ * 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 {LogsTableComponent} from './logs-table-component';
+
+describe('LogsTableComponent', () => {
+ let component;
+
+ beforeEach(() => {
+ component = new LogsTableComponent();
+ });
+
+ describe('#isColumnDisplayed()', () => {
+ const cases = [
+ {
+ name: 'v1',
+ result: true,
+ title: 'column is displayed'
+ },
+ {
+ name: 'l1',
+ result: false,
+ title: 'column is not displayed'
+ }
+ ];
+
+ beforeEach(() => {
+ component.displayedColumns = [
+ {
+ label: 'l0',
+ value: 'v0'
+ },
+ {
+ label: 'l1',
+ value: 'v1'
+ }
+ ];
+ });
+
+ cases.forEach(test => {
+ it(test.title, () => {
+ expect(component.isColumnDisplayed(test.name)).toEqual(test.result);
+ });
+ });
+ });
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.ts
new file mode 100644
index 0000000..0b8866a
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/components/logs-table-component.ts
@@ -0,0 +1,51 @@
+/**
+ * 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 {OnChanges, SimpleChanges, Input} from '@angular/core';
+import {FormGroup} from '@angular/forms';
+import {ListItem} from '@app/classes/list-item';
+import {ServiceLog} from '@app/classes/models/service-log';
+import {AuditLog} from '@app/classes/models/audit-log';
+
+export class LogsTableComponent implements OnChanges {
+
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes.hasOwnProperty('columns')) {
+ this.displayedColumns = this.columns.filter((column: ListItem): boolean => column.isChecked);
+ }
+ }
+
+ @Input()
+ logs: ServiceLog[] | AuditLog[] = [];
+
+ @Input()
+ columns: ListItem[] = [];
+
+ @Input()
+ filtersForm: FormGroup;
+
+ @Input()
+ totalCount: number = 0;
+
+ displayedColumns: ListItem[] = [];
+
+ isColumnDisplayed(key: string): boolean {
+ return this.displayedColumns.some((column: ListItem): boolean => column.value === key);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/audit-log.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/audit-log.ts b/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/audit-log.ts
index fbe0e46..380f14f 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/audit-log.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/classes/models/audit-log.ts
@@ -35,7 +35,7 @@ export interface AuditLog extends Log {
repoType: number;
repo: string;
proxyUsers?: string[];
- evtTime: string;
+ evtTime: number;
enforcer: string;
reqContext?: string;
cliType?: string;
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
new file mode 100644
index 0000000..d6e9091
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.html
@@ -0,0 +1,54 @@
+<!--
+ 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.
+-->
+
+<dropdown-button class="pull-right" label="logs.columns" [options]="columns" [isRightAlign]="true"
+ [isMultipleChoice]="true" action="updateSelectedColumns"
+ [additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button>
+<form *ngIf="logs && logs.length" [formGroup]="filtersForm" class="row pull-right">
+ <filter-dropdown class="col-md-12" [label]="filters.auditLogsSorting.label" formControlName="auditLogsSorting"
+ [options]="filters.auditLogsSorting.options" [isRightAlign]="true"></filter-dropdown></form>
+<div class="panel panel-default">
+ <div class="panel-body">
+ <table class="table">
+ <thead>
+ <tr>
+ <th *ngIf="isColumnDisplayed('evtTime')">{{getColumnByName('evtTime').label | translate}}</th>
+ <ng-container *ngFor="let column of displayedColumns">
+ <th *ngIf="customProcessedColumns.indexOf(column.value) === -1">{{column.label | translate}}</th>
+ </ng-container>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let log of logs">
+ <td *ngIf="isColumnDisplayed('evtTime')">{{log.evtTime | amTz: timeZone | amDateFormat: timeFormat}}</td>
+ <ng-container *ngFor="let column of displayedColumns">
+ <td *ngIf="customProcessedColumns.indexOf(column.value) === -1">{{log[column.value]}}</td>
+ </ng-container>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td attr.colspan="{{displayedColumns.length + 1}}">
+ <pagination class="col-md-12" *ngIf="logs && logs.length" [totalCount]="totalCount"
+ [filtersForm]="filtersForm" [filterInstance]="filters.pageSize"
+ [currentCount]="logs.length"></pagination>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.less
new file mode 100644
index 0000000..d9b0a10
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.less
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+
+th {
+ text-transform: uppercase;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
new file mode 100644
index 0000000..b6206db
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.spec.ts
@@ -0,0 +1,157 @@
+/**
+ * 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 {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
+import {StoreModule} from '@ngrx/store';
+import {MomentModule} from 'angular2-moment';
+import {MomentTimezoneModule} from 'angular-moment-timezone';
+import {TranslationModules} from '@app/test-config.spec';
+import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
+import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
+import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
+import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
+import {AppStateService, appState} from '@app/services/storage/app-state.service';
+import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
+import {TabsService, tabs} from '@app/services/storage/tabs.service';
+import {ClustersService, clusters} from '@app/services/storage/clusters.service';
+import {ComponentsService, components} from '@app/services/storage/components.service';
+import {HostsService, hosts} from '@app/services/storage/hosts.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {UtilsService} from '@app/services/utils.service';
+import {HttpClientService} from '@app/services/http-client.service';
+import {PaginationComponent} from '@app/components/pagination/pagination.component';
+import {DropdownListComponent} from '@app/components/dropdown-list/dropdown-list.component';
+
+import {AuditLogsTableComponent} from './audit-logs-table.component';
+
+describe('AuditLogsTableComponent', () => {
+ let component: AuditLogsTableComponent;
+ let fixture: ComponentFixture<AuditLogsTableComponent>;
+ const httpClient = {
+ get: () => {
+ return {
+ subscribe: () => {
+ }
+ };
+ }
+ };
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ AuditLogsTableComponent,
+ PaginationComponent,
+ DropdownListComponent
+ ],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ MomentModule,
+ MomentTimezoneModule,
+ ...TranslationModules,
+ StoreModule.provideStore({
+ auditLogs,
+ serviceLogs,
+ auditLogsFields,
+ serviceLogsFields,
+ serviceLogsHistogramData,
+ serviceLogsTruncated,
+ appState,
+ appSettings,
+ tabs,
+ clusters,
+ components,
+ hosts
+ })
+ ],
+ providers: [
+ LogsContainerService,
+ UtilsService,
+ {
+ provide: HttpClientService,
+ useValue: httpClient
+ },
+ AuditLogsService,
+ ServiceLogsService,
+ AuditLogsFieldsService,
+ ServiceLogsFieldsService,
+ ServiceLogsHistogramDataService,
+ ServiceLogsTruncatedService,
+ AppStateService,
+ AppSettingsService,
+ TabsService,
+ ClustersService,
+ ComponentsService,
+ HostsService
+ ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AuditLogsTableComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create component', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('#getColumnByName()', () => {
+ const cases = [
+ {
+ name: 'v1',
+ result: {
+ label: 'l1',
+ value: 'v1'
+ },
+ title: 'item is present'
+ },
+ {
+ name: 'l1',
+ result: undefined,
+ title: 'item is absent'
+ }
+ ];
+
+ beforeEach(() => {
+ component.columns = [
+ {
+ label: 'l0',
+ value: 'v0'
+ },
+ {
+ label: 'l1',
+ value: 'v1'
+ }
+ ];
+ });
+
+ cases.forEach(test => {
+ it(test.title, () => {
+ expect(component.getColumnByName(test.name)).toEqual(test.result);
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.ts
new file mode 100644
index 0000000..0e578ab
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/audit-logs-table/audit-logs-table.component.ts
@@ -0,0 +1,55 @@
+/**
+ * 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} from '@angular/core';
+import {ListItem} from '@app/classes/list-item';
+import {LogsTableComponent} from '@app/classes/components/logs-table-component';
+import {LogsContainerService} from '@app/services/logs-container.service';
+
+@Component({
+ selector: 'audit-logs-table',
+ templateUrl: './audit-logs-table.component.html',
+ styleUrls: ['./audit-logs-table.component.less']
+})
+export class AuditLogsTableComponent extends LogsTableComponent {
+
+ constructor(private logsContainer: LogsContainerService) {
+ super();
+ }
+
+ readonly customProcessedColumns: string[] = ['evtTime'];
+
+ readonly timeFormat: string = 'YYYY-MM-DD HH:mm:ss,SSS';
+
+ get logsTypeMapObject(): object {
+ return this.logsContainer.logsTypeMap.auditLogs;
+ }
+
+ get filters(): any {
+ return this.logsContainer.filters;
+ }
+
+ get timeZone(): string {
+ return this.logsContainer.timeZone;
+ }
+
+ getColumnByName(name: string): ListItem | undefined {
+ return this.columns.find((column: ListItem): boolean => column.value === name);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
index 3314252..b41f7cd 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.ts
@@ -97,7 +97,7 @@ export class FiltersPanelComponent {
}
isFilterConditionDisplayed(key: string): boolean {
- return this.logsContainer.filtersFormItemsMap[this.logsType].indexOf(key) > -1
+ return this.logsContainer.logsTypeMap[this.logsType].listFilters.indexOf(key) > -1
&& Boolean(this.filtersForm.controls[key]);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
index 2c3a3b9..f34dd15 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html
@@ -44,11 +44,12 @@
<time-histogram [data]="histogramData" [customOptions]="histogramOptions" svgId="service-logs-histogram"
(selectArea)="setCustomTimeRange($event[0], $event[1])"></time-histogram>
</collapsible-panel>
- <dropdown-button *ngIf="!isServiceLogsFileView" class="pull-right" label="logs.columns"
- [options]="availableColumns | async" [isRightAlign]="true" [isMultipleChoice]="true"
- action="updateSelectedColumns" [additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button>
- <logs-list [logs]="logs | async" [totalCount]="totalCount" [displayedColumns]="displayedColumns"
- [isServiceLogsFileView]="isServiceLogsFileView" [filtersForm]="filtersForm"></logs-list>
- <log-context *ngIf="isServiceLogContextView" [hostName]="activeLog.host_name" [componentName]="activeLog.component_name"
- [id]="activeLog.id"></log-context>
+ <ng-container [ngSwitch]="logsType">
+ <service-logs-table *ngSwitchCase="'serviceLogs'" [totalCount]="totalCount" [logs]="serviceLogs | async"
+ [columns]="serviceLogsColumns | async" [filtersForm]="filtersForm"></service-logs-table>
+ <audit-logs-table *ngSwitchCase="'auditLogs'" [totalCount]="totalCount" [logs]="auditLogs | async"
+ [columns]="auditLogsColumns | async" [filtersForm]="filtersForm"></audit-logs-table>
+ </ng-container>
+ <log-context *ngIf="isServiceLogContextView" [id]="activeLog.id" [hostName]="activeLog.host_name"
+ [componentName]="activeLog.component_name"></log-context>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
index f8acd50..b06cfa4 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts
@@ -19,16 +19,12 @@
import {Component} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {Observable} from 'rxjs/Observable';
-import {Subject} from 'rxjs/Subject';
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/takeUntil';
import {LogsContainerService} from '@app/services/logs-container.service';
import {ServiceLogsHistogramDataService} from '@app/services/storage/service-logs-histogram-data.service';
import {AppStateService} from '@app/services/storage/app-state.service';
import {TabsService} from '@app/services/storage/tabs.service';
import {AuditLog} from '@app/classes/models/audit-log';
import {ServiceLog} from '@app/classes/models/service-log';
-import {LogField} from '@app/classes/models/log-field';
import {Tab} from '@app/classes/models/tab';
import {BarGraph} from '@app/classes/models/bar-graph';
import {ActiveServiceLogEntry} from '@app/classes/active-service-log-entry';
@@ -47,35 +43,7 @@ export class LogsContainerComponent {
private tabsStorage: TabsService, private logsContainer: LogsContainerService
) {
this.logsContainer.loadColumnsNames();
- appState.getParameter('activeLogsType').subscribe((value: string): void => {
- this.logsType = value;
- this.logsTypeChange.next();
- const fieldsModel = this.logsTypeMapObject.fieldsModel,
- logsModel = this.logsTypeMapObject.logsModel;
- this.availableColumns = fieldsModel.getAll().takeUntil(this.logsTypeChange).map((fields: LogField[]): ListItem[] => {
- return fields.filter((field: LogField): boolean => field.isAvailable).map((field: LogField): ListItem => {
- return {
- value: field.name,
- label: field.displayName || field.name,
- isChecked: field.isDisplayed
- };
- });
- });
- fieldsModel.getAll().takeUntil(this.logsTypeChange).subscribe(columns => {
- const availableFields = columns.filter((field: LogField): boolean => field.isAvailable),
- availableNames = availableFields.map((field: LogField): string => field.name);
- if (availableNames.length) {
- this.logs = logsModel.getAll().map((logs: (AuditLog | ServiceLog)[]): (AuditLog | ServiceLog)[] => {
- return logs.map((log: AuditLog | ServiceLog): AuditLog | ServiceLog => {
- return availableNames.reduce((obj, key) => Object.assign(obj, {
- [key]: log[key]
- }), {});
- });
- });
- }
- this.displayedColumns = columns.filter((column: LogField): boolean => column.isAvailable && column.isDisplayed);
- });
- });
+ appState.getParameter('activeLogsType').subscribe((value: string) => this.logsType = value);
serviceLogsHistogramStorage.getAll().subscribe((data: BarGraph[]): void => {
this.histogramData = this.logsContainer.getHistogramData(data);
});
@@ -90,22 +58,10 @@ export class LogsContainerComponent {
private logsType: string;
- private logsTypeChange: Subject<any> = new Subject();
-
- get logsTypeMapObject(): any {
- return this.logsContainer.logsTypeMap[this.logsType];
- }
-
get totalCount(): number {
return this.logsContainer.totalCount;
}
- logs: Observable<AuditLog[] | ServiceLog[]>;
-
- availableColumns: Observable<LogField[]>;
-
- displayedColumns: any[] = [];
-
histogramData: {[key: string]: number};
readonly histogramOptions: HistogramOptions = {
@@ -142,6 +98,22 @@ export class LogsContainerComponent {
return this.logsContainer.activeLog;
}
+ get auditLogs(): Observable<AuditLog[]> {
+ return this.logsContainer.auditLogs;
+ }
+
+ get auditLogsColumns(): Observable<ListItem[]> {
+ return this.logsContainer.auditLogsColumns;
+ }
+
+ get serviceLogs(): Observable<ServiceLog[]> {
+ return this.logsContainer.serviceLogs;
+ }
+
+ get serviceLogsColumns(): Observable<ListItem[]> {
+ return this.logsContainer.serviceLogsColumns;
+ }
+
setCustomTimeRange(startTime: number, endTime: number): void {
this.logsContainer.setCustomTimeRange(startTime, endTime);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.html
deleted file mode 100644
index 7de0b96..0000000
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!--
- 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.
--->
-
-<form *ngIf="logs && logs.length" [formGroup]="filtersForm" class="row pull-right">
- <filter-dropdown [label]="filters.sorting.label" formControlName="sorting" [options]="filters.sorting.options"
- [isRightAlign]="true" class="col-md-12"></filter-dropdown>
-</form>
-<div class="panel panel-default">
- <div class="panel-body">
- <table class="table table-hover">
- <tbody>
- <ng-container *ngFor="let log of logs; let i = index">
- <tr *ngIf="!isServiceLogsFileView && (i === 0 || isDifferentDates(log.logtime, logs[i - 1].logtime))"
- class="log-date-row" >
- <th attr.colspan="{{displayedColumns.length + 1}}">
- {{log.logtime | amTz: timeZone | amDateFormat: dateFormat}}
- </th>
- </tr>
- <tr class="log-item-row">
- <td class="log-action">
- <dropdown-button iconClass="fa fa-ellipsis-h action" [hideCaret]="true" [options]="logActions"
- [additionalArgs]="[log]"></dropdown-button>
- </td>
- <td *ngIf="isColumnDisplayed('logtime')" class="log-time">
- <time>
- {{log.logtime | amTz: timeZone | amDateFormat: timeFormat}}
- </time>
- </td>
- <td *ngIf="isColumnDisplayed('level')" [ngClass]="'log-level ' + log.level.toLowerCase()">
- <log-level [logEntry]="log"></log-level>
- </td>
- <td *ngIf="isColumnDisplayed('type')" [ngClass]="'log-type'">
- {{log.type}}
- </td>
- <td *ngIf="isColumnDisplayed('log_message')" [ngClass]="'log-message'" width="*"
- (contextmenu)="openMessageContextMenu($event)">
- <log-message [listenChangesOn]="displayedColumns">{{log.log_message}}</log-message>
- </td>
- <ng-container *ngFor="let column of displayedColumns">
- <td *ngIf="customStyledColumns.indexOf(column.name) === -1"
- [ngClass]="'log-' + column.name">{{log[column.name]}}</td>
- </ng-container>
- </tr>
- </ng-container>
- </tbody>
- <tfoot>
- <tr>
- <td attr.colspan="{{displayedColumns.length + 1}}">
- <pagination class="col-md-12" *ngIf="logs && logs.length" [totalCount]="totalCount"
- [filtersForm]="filtersForm" [filterInstance]="filters.pageSize" [currentCount]="logs.length"></pagination>
- </td>
- </tr>
- </tfoot>
- </table>
- <ul #contextmenu data-component="dropdown-list" class="dropdown-menu context-menu" [items]="contextMenuItems"
- (selectedItemChange)="updateQuery($event)"></ul>
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less
deleted file mode 100644
index c5c4c5a..0000000
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * 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 '../mixins';
-
-:host {
- /deep/ filter-dropdown {
- justify-content: flex-end;
- }
-
- .panel-body {
- overflow: hidden;
- width: 100%;
- }
-
- table {
- width: 100%;
- }
-
- tr.log-date-row, tr.log-date-row:hover {
- background: @list-header-background-color;
- border: none transparent;
- th {
- border: none transparent;
- }
- }
- tr.log-item-row td {
- background: none transparent;
- }
-
- td {
- &.log-action {
- min-width: 3em;
- /deep/ .btn, /deep/ .filter-label {
- font-size: 1em;
- height: auto;
- line-height: 1em;
- padding: 0;
- }
- }
- &.log-time {
- color: @grey-color;
- min-width: 7em;
- text-align: right;
- }
- &.log-level {
- text-transform: uppercase;
- min-width: 8em;
- .log-colors;
- }
- &.log-type {
- color: @link-color;
- }
- &.log-message, &.log-path {
- width: 100%;
- }
- }
-
- tr:hover td.log-action {
- /deep/ .btn {
- display: inline-block;
- }
- }
-
- .table.table-hover>tbody>tr{
- box-sizing: border-box;
- border-width: 1px;
- >td {
- border-top: 0 none;
- }
- &:first-of-type {
- border-top-color: transparent;
- }
- &:last-of-type {
- border-bottom-color: transparent;
- }
- }
-
- .context-menu {
- position: fixed;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.spec.ts
deleted file mode 100644
index 21c4f02..0000000
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.spec.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * 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 {NO_ERRORS_SCHEMA} from '@angular/core';
-import {async, ComponentFixture, TestBed} from '@angular/core/testing';
-import {TranslationModules} from '@app/test-config.spec';
-import {StoreModule} from '@ngrx/store';
-import {MomentModule} from 'angular2-moment';
-import {MomentTimezoneModule} from 'angular-moment-timezone';
-import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
-import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
-import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
-import {AppStateService, appState} from '@app/services/storage/app-state.service';
-import {ClustersService, clusters} from '@app/services/storage/clusters.service';
-import {ComponentsService, components} from '@app/services/storage/components.service';
-import {HostsService, hosts} from '@app/services/storage/hosts.service';
-import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
-import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
-import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
-import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
-import {TabsService, tabs} from '@app/services/storage/tabs.service';
-import {HttpClientService} from '@app/services/http-client.service';
-import {LogsContainerService} from '@app/services/logs-container.service';
-import {UtilsService} from '@app/services/utils.service';
-
-import {LogsListComponent} from './logs-list.component';
-
-describe('LogsListComponent', () => {
- let component: LogsListComponent;
- let fixture: ComponentFixture<LogsListComponent>;
- const httpClient = {
- get: () => {
- return {
- subscribe: () => {
- }
- };
- }
- };
-
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- declarations: [LogsListComponent],
- imports: [
- StoreModule.provideStore({
- auditLogs,
- serviceLogs,
- appSettings,
- appState,
- clusters,
- components,
- hosts,
- auditLogsFields,
- serviceLogsFields,
- serviceLogsHistogramData,
- serviceLogsTruncated,
- tabs
- }),
- MomentModule,
- MomentTimezoneModule,
- ...TranslationModules
- ],
- providers: [
- {
- provide: HttpClientService,
- useValue: httpClient
- },
- AuditLogsService,
- ServiceLogsService,
- AppSettingsService,
- AppStateService,
- ClustersService,
- ComponentsService,
- HostsService,
- AuditLogsFieldsService,
- ServiceLogsFieldsService,
- ServiceLogsHistogramDataService,
- ServiceLogsTruncatedService,
- TabsService,
- LogsContainerService,
- UtilsService
- ],
- schemas: [NO_ERRORS_SCHEMA]
- })
- .compileComponents();
- }));
-
- beforeEach(() => {
- fixture = TestBed.createComponent(LogsListComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create component', () => {
- expect(component).toBeTruthy();
- });
-});
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.ts
deleted file mode 100644
index 3a56fca..0000000
--- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * 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, AfterViewInit, Input, ViewChild, ElementRef} from '@angular/core';
-import {FormGroup} from '@angular/forms';
-import 'rxjs/add/operator/map';
-import {LogsContainerService} from '@app/services/logs-container.service';
-import {UtilsService} from '@app/services/utils.service';
-import {AuditLog} from '@app/classes/models/audit-log';
-import {ServiceLog} from '@app/classes/models/service-log';
-import {LogField} from '@app/classes/models/log-field';
-
-@Component({
- selector: 'logs-list',
- templateUrl: './logs-list.component.html',
- styleUrls: ['./logs-list.component.less']
-})
-export class LogsListComponent implements AfterViewInit {
-
- constructor(private logsContainer: LogsContainerService, private utils: UtilsService) {
- }
-
- ngAfterViewInit() {
- if (this.contextMenu) {
- this.contextMenuElement = this.contextMenu.nativeElement;
- }
- }
-
- @Input()
- logs: (AuditLog| ServiceLog)[] = [];
-
- @Input()
- totalCount: number = 0;
-
- @Input()
- displayedColumns: LogField[] = [];
-
- @Input()
- isServiceLogsFileView: boolean = false;
-
- @Input()
- filtersForm: FormGroup;
-
- @ViewChild('contextmenu', {
- read: ElementRef
- })
- contextMenu: ElementRef;
-
- private contextMenuElement: HTMLElement;
-
- private selectedText: string = '';
-
- private readonly messageFilterParameterName = 'log_message';
-
- readonly customStyledColumns = ['level', 'type', 'logtime', 'log_message'];
-
- readonly contextMenuItems = [
- {
- label: 'logs.addToQuery',
- iconClass: 'fa fa-search-plus',
- value: false // 'isExclude' is false
- },
- {
- label: 'logs.excludeFromQuery',
- iconClass: 'fa fa-search-minus',
- value: true // 'isExclude' is true
- }
- ];
-
- readonly logActions = [
- {
- label: 'logs.copy',
- iconClass: 'fa fa-files-o',
- action: 'copyLog'
- },
- {
- label: 'logs.open',
- iconClass: 'fa fa-external-link',
- action: 'openLog'
- },
- {
- label: 'logs.context',
- iconClass: 'fa fa-crosshairs',
- action: 'openContext'
- }
- ];
-
- readonly dateFormat: string = 'dddd, MMMM Do';
-
- readonly timeFormat: string = 'h:mm:ss A';
-
- get timeZone(): string {
- return this.logsContainer.timeZone;
- }
-
- get filters(): any {
- return this.logsContainer.filters;
- }
-
- isDifferentDates(dateA, dateB): boolean {
- return this.utils.isDifferentDates(dateA, dateB, this.timeZone);
- }
-
- isColumnDisplayed(key: string): boolean {
- return this.displayedColumns.some((column: LogField): boolean => column.name === key);
- }
-
- openMessageContextMenu(event: MouseEvent): void {
- const selectedText = getSelection().toString();
- if (selectedText) {
- let contextMenuStyle = this.contextMenuElement.style;
- Object.assign(contextMenuStyle, {
- left: `${event.clientX}px`,
- top: `${event.clientY}px`,
- display: 'block'
- });
- this.selectedText = selectedText;
- document.body.addEventListener('click', this.dismissContextMenu);
- event.preventDefault();
- }
- }
-
- updateQuery(event: any) {
- this.logsContainer.queryParameterAdd.next({
- name: this.messageFilterParameterName,
- value: this.selectedText,
- isExclude: event.value
- });
- }
-
- private dismissContextMenu = (): void => {
- this.selectedText = '';
- this.contextMenuElement.style.display = 'none';
- document.body.removeEventListener('click', this.dismissContextMenu);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
new file mode 100644
index 0000000..a2e666e
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.html
@@ -0,0 +1,76 @@
+<!--
+ 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.
+-->
+
+<dropdown-button class="pull-right" label="logs.columns" [options]="columns" [isRightAlign]="true"
+ [isMultipleChoice]="true" action="updateSelectedColumns"
+ [additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button>
+<form *ngIf="logs && logs.length" [formGroup]="filtersForm" class="row pull-right">
+ <filter-dropdown class="col-md-12" [label]="filters.serviceLogsSorting.label" formControlName="serviceLogsSorting"
+ [options]="filters.serviceLogsSorting.options" [isRightAlign]="true"></filter-dropdown>
+</form>
+<div class="panel panel-default">
+ <div class="panel-body">
+ <table class="table table-hover">
+ <tbody>
+ <ng-container *ngFor="let log of logs; let i = index">
+ <tr *ngIf="i === 0 || isDifferentDates(log.logtime, logs[i - 1].logtime)" class="log-date-row">
+ <th attr.colspan="{{displayedColumns.length + 1}}">
+ {{log.logtime | amTz: timeZone | amDateFormat: dateFormat}}
+ </th>
+ </tr>
+ <tr class="log-item-row">
+ <td class="log-action">
+ <dropdown-button iconClass="fa fa-ellipsis-h action" [hideCaret]="true" [options]="logActions"
+ [additionalArgs]="[log]"></dropdown-button>
+ </td>
+ <td *ngIf="isColumnDisplayed('logtime')" class="log-time">
+ <time>
+ {{log.logtime | amTz: timeZone | amDateFormat: timeFormat}}
+ </time>
+ </td>
+ <td *ngIf="isColumnDisplayed('level')" [ngClass]="'log-level ' + log.level.toLowerCase()">
+ <log-level [logEntry]="log"></log-level>
+ </td>
+ <td *ngIf="isColumnDisplayed('type')" [ngClass]="'log-type'">
+ {{log.type}}
+ </td>
+ <td *ngIf="isColumnDisplayed('log_message')" [ngClass]="'log-message'" width="*"
+ (contextmenu)="openMessageContextMenu($event)">
+ <log-message [listenChangesOn]="displayedColumns">{{log.log_message}}</log-message>
+ </td>
+ <ng-container *ngFor="let column of displayedColumns">
+ <td *ngIf="customStyledColumns.indexOf(column.value) === -1" [ngClass]="'log-' + column.value">
+ {{log[column.value]}}
+ </td>
+ </ng-container>
+ </tr>
+ </ng-container>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td attr.colspan="{{displayedColumns.length + 1}}">
+ <pagination class="col-md-12" *ngIf="logs && logs.length" [totalCount]="totalCount"
+ [filtersForm]="filtersForm" [filterInstance]="filters.pageSize"
+ [currentCount]="logs.length"></pagination>
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+ <ul #contextmenu data-component="dropdown-list" class="dropdown-menu context-menu" [items]="contextMenuItems"
+ (selectedItemChange)="updateQuery($event)"></ul>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
new file mode 100644
index 0000000..bd6d012
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.less
@@ -0,0 +1,97 @@
+/**
+ * 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 '../mixins';
+
+:host {
+ /deep/ filter-dropdown {
+ justify-content: flex-end;
+ }
+
+ .panel-body {
+ overflow: hidden;
+ width: 100%;
+ }
+
+ table {
+ width: 100%;
+ }
+
+ tr.log-date-row, tr.log-date-row:hover {
+ background: @list-header-background-color;
+ border: none transparent;
+ th {
+ border: none transparent;
+ }
+ }
+ tr.log-item-row td {
+ background: none transparent;
+ }
+
+ td {
+ &.log-action {
+ min-width: 3em;
+ /deep/ .btn, /deep/ .filter-label {
+ font-size: 1em;
+ height: auto;
+ line-height: 1em;
+ padding: 0;
+ }
+ }
+ &.log-time {
+ color: @grey-color;
+ min-width: 7em;
+ text-align: right;
+ }
+ &.log-level {
+ text-transform: uppercase;
+ min-width: 8em;
+ .log-colors;
+ }
+ &.log-type {
+ color: @link-color;
+ }
+ &.log-message, &.log-path {
+ width: 100%;
+ }
+ }
+
+ tr:hover td.log-action {
+ /deep/ .btn {
+ display: inline-block;
+ }
+ }
+
+ .table.table-hover > tbody > tr {
+ box-sizing: border-box;
+ border-width: 1px;
+ > td {
+ border-top: 0 none;
+ }
+ &:first-of-type {
+ border-top-color: transparent;
+ }
+ &:last-of-type {
+ border-bottom-color: transparent;
+ }
+ }
+
+ .context-menu {
+ position: fixed;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
new file mode 100644
index 0000000..0c323f7
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.spec.ts
@@ -0,0 +1,126 @@
+/**
+ * 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 {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
+import {StoreModule} from '@ngrx/store';
+import {MomentModule} from 'angular2-moment';
+import {MomentTimezoneModule} from 'angular-moment-timezone';
+import {TranslationModules} from '@app/test-config.spec';
+import {AuditLogsService, auditLogs} from '@app/services/storage/audit-logs.service';
+import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service';
+import {AuditLogsFieldsService, auditLogsFields} from '@app/services/storage/audit-logs-fields.service';
+import {ServiceLogsFieldsService, serviceLogsFields} from '@app/services/storage/service-logs-fields.service';
+import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service';
+import {ServiceLogsTruncatedService, serviceLogsTruncated} from '@app/services/storage/service-logs-truncated.service';
+import {AppStateService, appState} from '@app/services/storage/app-state.service';
+import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
+import {TabsService, tabs} from '@app/services/storage/tabs.service';
+import {ClustersService, clusters} from '@app/services/storage/clusters.service';
+import {ComponentsService, components} from '@app/services/storage/components.service';
+import {HostsService, hosts} from '@app/services/storage/hosts.service';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {UtilsService} from '@app/services/utils.service';
+import {HttpClientService} from '@app/services/http-client.service';
+import {ComponentGeneratorService} from '@app/services/component-generator.service';
+import {ComponentActionsService} from '@app/services/component-actions.service';
+import {AuthService} from '@app/services/auth.service';
+import {PaginationComponent} from '@app/components/pagination/pagination.component';
+import {DropdownListComponent} from '@app/components/dropdown-list/dropdown-list.component';
+
+import {ServiceLogsTableComponent} from './service-logs-table.component';
+
+describe('ServiceLogsTableComponent', () => {
+ let component: ServiceLogsTableComponent;
+ let fixture: ComponentFixture<ServiceLogsTableComponent>;
+ const httpClient = {
+ get: () => {
+ return {
+ subscribe: () => {
+ }
+ };
+ }
+ };
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ ServiceLogsTableComponent,
+ PaginationComponent,
+ DropdownListComponent
+ ],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ MomentModule,
+ MomentTimezoneModule,
+ ...TranslationModules,
+ StoreModule.provideStore({
+ auditLogs,
+ serviceLogs,
+ auditLogsFields,
+ serviceLogsFields,
+ serviceLogsHistogramData,
+ serviceLogsTruncated,
+ appState,
+ appSettings,
+ tabs,
+ clusters,
+ components,
+ hosts
+ })
+ ],
+ providers: [
+ LogsContainerService,
+ UtilsService,
+ {
+ provide: HttpClientService,
+ useValue: httpClient
+ },
+ AuditLogsService,
+ ServiceLogsService,
+ AuditLogsFieldsService,
+ ServiceLogsFieldsService,
+ ServiceLogsHistogramDataService,
+ ServiceLogsTruncatedService,
+ AppStateService,
+ AppSettingsService,
+ TabsService,
+ ClustersService,
+ ComponentsService,
+ HostsService,
+ ComponentGeneratorService,
+ ComponentActionsService,
+ AuthService
+ ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ServiceLogsTableComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create component', () => {
+ expect(component).toBeTruthy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.ts
new file mode 100644
index 0000000..9f38371
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/service-logs-table/service-logs-table.component.ts
@@ -0,0 +1,135 @@
+/**
+ * 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, AfterViewInit, ViewChild, ElementRef} from '@angular/core';
+import {ListItem} from '@app/classes/list-item';
+import {LogsTableComponent} from '@app/classes/components/logs-table-component';
+import {LogsContainerService} from '@app/services/logs-container.service';
+import {UtilsService} from '@app/services/utils.service';
+
+@Component({
+ selector: 'service-logs-table',
+ templateUrl: './service-logs-table.component.html',
+ styleUrls: ['./service-logs-table.component.less']
+})
+export class ServiceLogsTableComponent extends LogsTableComponent implements AfterViewInit {
+
+ constructor(private logsContainer: LogsContainerService, private utils: UtilsService) {
+ super();
+ }
+
+ ngAfterViewInit() {
+ if (this.contextMenu) {
+ this.contextMenuElement = this.contextMenu.nativeElement;
+ }
+ }
+
+ @ViewChild('contextmenu', {
+ read: ElementRef
+ })
+ contextMenu: ElementRef;
+
+ readonly dateFormat: string = 'dddd, MMMM Do';
+
+ readonly timeFormat: string = 'h:mm:ss A';
+
+ readonly logActions = [
+ {
+ label: 'logs.copy',
+ iconClass: 'fa fa-files-o',
+ action: 'copyLog'
+ },
+ {
+ label: 'logs.open',
+ iconClass: 'fa fa-external-link',
+ action: 'openLog'
+ },
+ {
+ label: 'logs.context',
+ iconClass: 'fa fa-crosshairs',
+ action: 'openContext'
+ }
+ ];
+
+ readonly customStyledColumns: string[] = ['level', 'type', 'logtime', 'log_message'];
+
+ readonly contextMenuItems: ListItem[] = [
+ {
+ label: 'logs.addToQuery',
+ iconClass: 'fa fa-search-plus',
+ value: false // 'isExclude' is false
+ },
+ {
+ label: 'logs.excludeFromQuery',
+ iconClass: 'fa fa-search-minus',
+ value: true // 'isExclude' is true
+ }
+ ];
+
+ private readonly messageFilterParameterName: string = 'log_message';
+
+ private contextMenuElement: HTMLElement;
+
+ private selectedText: string = '';
+
+ get timeZone(): string {
+ return this.logsContainer.timeZone;
+ }
+
+ get filters(): any {
+ return this.logsContainer.filters;
+ }
+
+ get logsTypeMapObject(): object {
+ return this.logsContainer.logsTypeMap.serviceLogs;
+ }
+
+ isDifferentDates(dateA, dateB): boolean {
+ return this.utils.isDifferentDates(dateA, dateB, this.timeZone);
+ }
+
+ openMessageContextMenu(event: MouseEvent): void {
+ const selectedText = getSelection().toString();
+ if (selectedText) {
+ let contextMenuStyle = this.contextMenuElement.style;
+ Object.assign(contextMenuStyle, {
+ left: `${event.clientX}px`,
+ top: `${event.clientY}px`,
+ display: 'block'
+ });
+ this.selectedText = selectedText;
+ document.body.addEventListener('click', this.dismissContextMenu);
+ event.preventDefault();
+ }
+ }
+
+ updateQuery(event: ListItem): void {
+ this.logsContainer.queryParameterAdd.next({
+ name: this.messageFilterParameterName,
+ value: this.selectedText,
+ isExclude: event.value
+ });
+ }
+
+ private dismissContextMenu = (): void => {
+ this.selectedText = '';
+ this.contextMenuElement.style.display = 'none';
+ document.body.removeEventListener('click', this.dismissContextMenu);
+ };
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts b/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
index 147efef..7578867 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/mock-data.ts
@@ -47,7 +47,7 @@ export const mockData = {
proxyUsers: [
'admin'
],
- evtTime: '2017-05-29T11:30:22.531Z',
+ evtTime: 1496057422531,
enforcer: 'ambari-acl',
reqContext: 'ambari',
cliType: 'GET',
@@ -94,7 +94,7 @@ export const mockData = {
proxyUsers: [
'user'
],
- evtTime: '2017-05-29T11:30:22.531Z',
+ evtTime: 1496057422531,
enforcer: 'hdfs',
reqContext: 'ambari_server',
cliType: 'PUT',
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.spec.ts
index fd5a83e..65f0936 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.spec.ts
@@ -55,7 +55,7 @@ describe('AuthService', () => {
isError: false,
postFormData: function () {
const isError = this.isError;
- return Observable.create(observer => observer.next(isError ? errorResponse : successResponse)).delay(1000);
+ return Observable.create(observer => observer.next(isError ? errorResponse : successResponse)).delay(1);
}
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
index f45887b..90ab9b7 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/logs-container.service.ts
@@ -22,6 +22,9 @@ import {Response} from '@angular/http';
import {Subject} from 'rxjs/Subject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/timer';
+import 'rxjs/add/observable/combineLatest';
+import 'rxjs/add/operator/first';
+import 'rxjs/add/operator/map';
import 'rxjs/add/operator/takeUntil';
import * as moment from 'moment-timezone';
import {HttpClientService} from '@app/services/http-client.service';
@@ -41,7 +44,10 @@ import {ActiveServiceLogEntry} from '@app/classes/active-service-log-entry';
import {FilterCondition, TimeUnitListItem, SortingListItem} from '@app/classes/filtering';
import {ListItem} from '@app/classes/list-item';
import {Tab} from '@app/classes/models/tab';
+import {LogField} from '@app/classes/models/log-field';
+import {AuditLog} from '@app/classes/models/audit-log';
import {AuditLogField} from '@app/classes/models/audit-log-field';
+import {ServiceLog} from '@app/classes/models/service-log';
import {ServiceLogField} from '@app/classes/models/service-log-field';
import {BarGraph} from '@app/classes/models/bar-graph';
import {NodeItem} from '@app/classes/models/node-item';
@@ -383,7 +389,35 @@ export class LogsContainerService {
options: [],
defaultSelection: []
},
- sorting: {
+ auditLogsSorting: {
+ label: 'sorting.title',
+ options: [
+ {
+ label: 'sorting.time.asc',
+ value: {
+ key: 'evtTime',
+ type: 'asc'
+ }
+ },
+ {
+ label: 'sorting.time.desc',
+ value: {
+ key: 'evtTime',
+ type: 'desc'
+ }
+ }
+ ],
+ defaultSelection: [
+ {
+ label: 'sorting.time.desc',
+ value: {
+ key: 'evtTime',
+ type: 'desc'
+ }
+ }
+ ]
+ },
+ serviceLogsSorting: {
label: 'sorting.title',
options: [
{
@@ -432,11 +466,6 @@ export class LogsContainerService {
query: {}
};
- readonly filtersFormItemsMap: {[key: string]: string[]} = {
- serviceLogs: ['clusters', 'timeRange', 'components', 'levels', 'hosts', 'sorting', 'pageSize', 'page', 'query'],
- auditLogs: ['clusters', 'timeRange', 'sorting', 'pageSize', 'page', 'query'] // TODO add all the required fields
- };
-
readonly colors = {
WARN: '#FF8916',
ERROR: '#E81D1D',
@@ -447,13 +476,14 @@ export class LogsContainerService {
UNKNOWN: '#BDBDBD'
};
- private readonly listFilters = {
+ private readonly filtersMapping = {
clusters: ['clusters'],
timeRange: ['to', 'from'],
components: ['mustBe'],
levels: ['level'],
hosts: ['hostList'],
- sorting: ['sortType', 'sortBy'],
+ auditLogsSorting: ['sortType', 'sortBy'],
+ serviceLogsSorting: ['sortType', 'sortBy'],
pageSize: ['pageSize'],
page: ['page'],
query: ['includeQuery', 'excludeQuery']
@@ -471,11 +501,16 @@ export class LogsContainerService {
readonly logsTypeMap = {
auditLogs: {
logsModel: this.auditLogsStorage,
- fieldsModel: this.auditLogsFieldsStorage
+ fieldsModel: this.auditLogsFieldsStorage,
+ // TODO add all the required fields
+ listFilters: ['clusters', 'timeRange', 'auditLogsSorting', 'pageSize', 'page', 'query'],
+ histogramFilters: ['clusters', 'timeRange', 'query']
},
serviceLogs: {
logsModel: this.serviceLogsStorage,
- fieldsModel: this.serviceLogsFieldsStorage
+ fieldsModel: this.serviceLogsFieldsStorage,
+ listFilters: ['clusters', 'timeRange', 'components', 'levels', 'hosts', 'serviceLogsSorting', 'pageSize', 'page', 'query'],
+ histogramFilters: ['clusters', 'timeRange', 'components', 'levels', 'hosts', 'query']
}
};
@@ -502,6 +537,38 @@ export class LogsContainerService {
private filtersFormChange: Subject<any> = new Subject();
+ private columnsMapper<FieldT extends LogField>(fields: FieldT[]): ListItem[] {
+ return fields.filter((field: FieldT): boolean => field.isAvailable).map((field: FieldT): ListItem => {
+ return {
+ value: field.name,
+ label: field.displayName || field.name,
+ isChecked: field.isDisplayed
+ };
+ });
+ }
+
+ private logsMapper<LogT extends AuditLog & ServiceLog>(result: [LogT[], ListItem[]]): LogT[] {
+ const [logs, fields] = result;
+ if (fields.length) {
+ const names = fields.map((field: ListItem): string => field.value);
+ return logs.map((log: LogT): LogT => {
+ return names.reduce((currentObject: object, key: string) => Object.assign(currentObject, {
+ [key]: log[key]
+ }), {}) as LogT;
+ });
+ } else {
+ return [];
+ }
+ }
+
+ auditLogsColumns: Observable<ListItem[]> = this.auditLogsFieldsStorage.getAll().map(this.columnsMapper);
+
+ serviceLogsColumns: Observable<ListItem[]> = this.serviceLogsFieldsStorage.getAll().map(this.columnsMapper);
+
+ serviceLogs: Observable<ServiceLog[]> = Observable.combineLatest(this.serviceLogsStorage.getAll(), this.serviceLogsColumns).map(this.logsMapper);
+
+ auditLogs: Observable<AuditLog[]> = Observable.combineLatest(this.auditLogsStorage.getAll(), this.auditLogsColumns).map(this.logsMapper);
+
/**
* Get instance for dropdown list from string
* @param name {string}
@@ -604,11 +671,11 @@ export class LogsContainerService {
});
}
- private getParams(filtersMapName: string): {[key: string]: string} {
+ private getParams(filtersMapName: string, logsType: string = this.activeLogsType): {[key: string]: string} {
let params = {};
- Object.keys(this[filtersMapName]).forEach((key: string): void => {
+ this.logsTypeMap[logsType][filtersMapName].forEach((key: string): void => {
const inputValue = this.filtersForm.getRawValue()[key],
- paramNames = this[filtersMapName][key];
+ paramNames = this.filtersMapping[key];
paramNames.forEach((paramName: string): void => {
let value;
const valueGetter = this.valueGetters[paramName] || this.defaultValueGetter;
@@ -845,7 +912,7 @@ export class LogsContainerService {
}
getFiltersData(listType: string): object {
- const itemsList = this.filtersFormItemsMap[listType],
+ const itemsList = this.logsTypeMap[listType].listFilters,
keys = Object.keys(this.filters).filter((key: string): boolean => itemsList.indexOf(key) > -1);
return keys.reduce((currentObject: object, key: string): object => {
return Object.assign(currentObject, {
http://git-wip-us.apache.org/repos/asf/ambari/blob/cc535c84/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts b/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
index 8b157df..985b52f 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/mock-api-data.service.ts
@@ -65,6 +65,28 @@ export class mockApiDataService implements InMemoryDbService {
isValuesList: true
}
}
+ },
+ 'api/v1/audit/logs': {
+ pathToCollection: 'logList',
+ totalCountKey: 'totalCount',
+ filters: {
+ clusters: {
+ key: 'cluster',
+ isValuesList: true
+ },
+ iMessage: {
+ key: 'log_message',
+ filterFunction: (value, filterValue) => value.toLowerCase().indexOf(filterValue.toLowerCase()) > -1
+ },
+ from: {
+ key: 'evtTime',
+ filterFunction: (value, filterValue) => value >= moment(filterValue).valueOf()
+ },
+ to: {
+ key: 'evtTime',
+ filterFunction: (value, filterValue) => value < moment(filterValue).valueOf()
+ }
+ }
}
};