Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

Commit

Permalink
feat(vm-logs): log files (#1351)
Browse files Browse the repository at this point in the history
* feat(vm-logs): log files

* feat(vm-logs): log files

* code style
  • Loading branch information
Vladimir Shakhov authored Oct 19, 2018
1 parent 2fa5125 commit 6953691
Show file tree
Hide file tree
Showing 21 changed files with 624 additions and 222 deletions.
104 changes: 75 additions & 29 deletions src/app/vm-logs/containers/vm-logs-filter.container.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { AfterViewInit, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { select, Store } from '@ngrx/store';
import { takeUntil, debounceTime } from 'rxjs/operators';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { State } from '../../reducers';
import { FilterService } from '../../shared/services/filter.service';
import { SessionStorageService } from '../../shared/services/session-storage.service';
import { WithUnsubscribe } from '../../utils/mixins/with-unsubscribe';
import * as vmActions from '../../reducers/vm/redux/vm.actions';
import * as vmLogActions from '../redux/vm-logs.actions';
import * as fromVMs from '../../reducers/vm/redux/vm.reducers';
import * as fromVmLogsVm from '../redux/vm-logs-vm.reducers';
import * as fromVmLogs from '../redux/vm-logs.reducers';
import * as fromVmLogFiles from '../redux/vm-log-files.reducers';
import * as fromAccounts from '../../reducers/accounts/redux/accounts.reducers';
import { Keyword } from '../models/keyword.model';
import { Time } from '../../shared/components/time-picker/time-picker.component';
import { UserTagsSelectors } from '../../root-store';
import moment = require('moment');
import * as accountActions from '../../reducers/accounts/redux/accounts.actions';
import { combineLatest } from 'rxjs';
import moment = require('moment');
import { VmLogFile } from '../models/vm-log-file.model';
import { selectFilteredVMs } from '../redux/selectors/filteredVms.selector';

const FILTER_KEY = 'logsFilters';

Expand All @@ -26,8 +31,10 @@ const FILTER_KEY = 'logsFilters';
*loading="loading$ | async"
[accounts]="accounts$ | async"
[vms]="vms$ | async"
[logFiles]="logFiles$ | async"
[selectedAccountIds]="selectedAccountIds$ | async"
[selectedVmId]="selectedVmId$ | async"
[selectedLogFile]="selectedLogFile$ | async"
[keywords]="keywords$ | async"
[startDate]="startDate$ | async | dateObjectToDate"
[startTime]="startTime$ | async"
Expand All @@ -37,6 +44,7 @@ const FILTER_KEY = 'logsFilters';
[firstDayOfWeek]="firstDayOfWeek$ | async"
(onAccountsChange)="onAccountsChange($event)"
(onVmChange)="onVmChange($event)"
(onLogFileChange)="onLogFileChange($event)"
(onRefresh)="onRefresh()"
(onKeywordAdd)="onKeywordAdd($event)"
(onKeywordRemove)="onKeywordRemove($event)"
Expand All @@ -48,26 +56,29 @@ const FILTER_KEY = 'logsFilters';
></cs-vm-logs-filter>`
})
export class VmLogsFilterContainerComponent extends WithUnsubscribe() implements OnInit, AfterViewInit {
readonly filters$ = this.store.pipe(select(fromVmLogs.filters));
readonly loading$ = this.store.pipe(select(fromVMs.isLoading));
readonly accounts$ = this.store.pipe(select(fromAccounts.selectAll));
readonly selectedAccountIds$ = this.store.pipe(select(fromVmLogs.filterSelectedAccountIds));
readonly vms$ = this.store.pipe(select(fromVmLogs.selectFilteredVMs));
readonly selectedVmId$ = this.store.pipe(select(fromVmLogs.filterSelectedVmId));
readonly selectedAccountIds$ = this.store.pipe(select(fromVmLogsVm.filterSelectedAccountIds));
readonly vms$ = this.store.pipe(select(selectFilteredVMs));
readonly selectedVmId$ = this.store.pipe(select(fromVmLogsVm.filterSelectedVmId));
readonly keywords$ = this.store.pipe(select(fromVmLogs.filterKeywords));
readonly startDate$ = this.store.pipe(select(fromVmLogs.filterStartDate));
readonly startTime$ = this.store.pipe(select(fromVmLogs.filterStartTime));
readonly endDate$ = this.store.pipe(select(fromVmLogs.filterEndDate));
readonly endTime$ = this.store.pipe(select(fromVmLogs.filterEndTime));
readonly firstDayOfWeek$ = this.store.pipe(select(UserTagsSelectors.getFirstDayOfWeek));
readonly newestFirst$ = this.store.pipe(select(fromVmLogs.filterNewestFirst));
readonly selectedLogFile$ = this.store.pipe(select(fromVmLogs.filterSelectedLogFile));
readonly logFiles$ = this.store.pipe(select(fromVmLogFiles.selectAll));

private filterService = new FilterService(
{
vm: { type: 'string' },
accounts: { type: 'array', defaultOption: [] },
keywords: { type: 'array', defaultOption: [] },
startDate: { type: 'string' },
endDate: { type: 'string' },
logFile: { type: 'string' },
newestFirst: { type: 'boolean' }
},
this.router,
Expand All @@ -91,9 +102,7 @@ export class VmLogsFilterContainerComponent extends WithUnsubscribe() implements
}

public onVmChange(selectedVmId: string) {
this.store.dispatch(new vmLogActions.VmLogsFilterUpdate({
selectedVmId
}));
this.store.dispatch(new vmLogActions.VmLogsUpdateVmId(selectedVmId));
}

public onRefresh() {
Expand Down Expand Up @@ -124,39 +133,76 @@ export class VmLogsFilterContainerComponent extends WithUnsubscribe() implements
this.store.dispatch(new vmLogActions.VmLogsUpdateEndTime(time));
}

public onLogFileChange(logFile: string) {
this.store.dispatch(new vmLogActions.VmLogsUpdateLogFile(logFile));
}

public onNewestFirstChange() {
this.store.dispatch(new vmLogActions.VmLogsToggleNewestFirst());
}

private initFilters(): void {
const params = this.filterService.getParams();

this.store.dispatch(new vmLogActions.VmLogsFilterUpdate({
selectedVmId: params['vm'],
keywords: (params['keywords'] || []).map(text => ({ text })),
newestFirst: params['newestFirst'],
selectedAccountIds: params['accounts'] || [],
...(params['startDate'] ? { startDate: moment(params['startDate']).toObject() } : null),
...(params['endDate'] ? { endDate: moment(params['endDate']).toObject() } : null)
}));
const {
vm,
keywords,
accounts,
startDate,
endDate,
logFile,
newestFirst
} = this.filterService.getParams();

this.store.dispatch(new vmLogActions.VmLogsUpdateVmId(vm));

const wrappedKeywords = (keywords || []).map(text => ({ text }));
this.store.dispatch(new vmLogActions.VmLogsUpdateKeywords(wrappedKeywords));
this.store.dispatch(new vmLogActions.VmLogsUpdateAccountIds(accounts || []));
this.store.dispatch(new vmLogActions.VmLogsUpdateNewestFirst(newestFirst));

if (logFile) {
this.store.dispatch(new vmLogActions.VmLogsUpdateLogFile(logFile));
}

if (startDate) {
this.store.dispatch(new vmLogActions.VmLogsUpdateStartDateTime(
moment(startDate).toObject()
));
}

if (endDate) {
this.store.dispatch(new vmLogActions.VmLogsUpdateEndDateTime(
moment(endDate).toObject()
));
}
}

public ngOnInit() {
this.store.dispatch(new vmActions.LoadVMsRequest());
this.store.dispatch(new accountActions.LoadAccountsRequest());
this.initFilters();
this.filters$.pipe(
takeUntil(this.unsubscribe$),
debounceTime(100)

combineLatest(
this.keywords$,
this.startDate$,
this.endDate$,
this.selectedVmId$,
this.selectedAccountIds$,
this.selectedLogFile$,
this.newestFirst$
)
.subscribe(filters => {
.pipe(
takeUntil(this.unsubscribe$),
debounceTime(100)
)
.subscribe(([keywords, startDate, endDate, vm, accounts, logFile, newestFirst]) => {
this.filterService.update({
vm: filters.selectedVmId,
keywords: filters.keywords.map(keyword => keyword.text),
accounts: filters.selectedAccountIds,
newestFirst: filters.newestFirst,
startDate: moment(filters.startDate).toISOString(),
endDate: moment(filters.endDate).toISOString(),
vm,
accounts,
keywords: keywords.map(keyword => keyword.text),
startDate: moment(startDate).toISOString(),
endDate: moment(endDate).toISOString(),
logFile,
newestFirst
});
});
}
Expand Down
7 changes: 7 additions & 0 deletions src/app/vm-logs/models/load-vm-log-files-request-params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface LoadVmLogFilesRequestParams {
id: string;
startdate?: string;
enddate?: string;
page?: number;
pagesize?: number;
}
3 changes: 3 additions & 0 deletions src/app/vm-logs/models/vm-log-file.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface VmLogFile {
file: string;
}
34 changes: 34 additions & 0 deletions src/app/vm-logs/redux/selectors/filteredVms.selector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createSelector } from '@ngrx/store';
import * as fromVMs from '../../../reducers/vm/redux/vm.reducers';
import { filterSelectedAccountIds, filterSelectedVmId } from '../vm-logs-vm.reducers';
import * as fromAccounts from '../../../reducers/accounts/redux/accounts.reducers';

export const selectFilteredVMs = createSelector(
fromVMs.selectAll,
filterSelectedAccountIds,
filterSelectedVmId,
fromAccounts.selectAll,
(
vms,
selectedAccountIds,
selectedVmId,
accounts
) => {
const selectedAccounts = accounts.filter(
account => selectedAccountIds.find(id => id === account.id));
const accountsMap = selectedAccounts.reduce((m, i) => ({ ...m, [i.name]: i }), {});
const domainsMap = selectedAccounts.reduce((m, i) => ({ ...m, [i.domainid]: i }), {});

const selectedAccountIdsFilter = vm => !selectedAccountIds.length ||
(accountsMap[vm.account] && domainsMap[vm.domainid]);

const selectedVm = vms.find(vm => vm.id === selectedVmId);
const filteredVms = vms.filter(vm => selectedAccountIdsFilter(vm));

if (!filteredVms.find(vm => vm.id === selectedVmId) && selectedVm) {
return filteredVms.concat(selectedVm);
}

return filteredVms;
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createSelector } from '@ngrx/store';
import { filterSelectedVmId } from '../vm-logs-vm.reducers';
import { LoadVmLogFilesRequestParams } from '../../models/load-vm-log-files-request-params';

export const loadVmLogFilesRequestParams = createSelector(
filterSelectedVmId,
(id): LoadVmLogFilesRequestParams => ({
id
})
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { loadVmLogsRequestParams } from './loadVmLogsRequestParams.selector';
import moment = require('moment');


describe('loadVmLogsRequestParams selector', () => {
const date = moment(0);

beforeAll(() => {
jasmine.clock().mockDate(date.toDate());
});

it('should select load logs request params without keywords', () => {
const id = 'test-id';
const keywords = [];

const params = loadVmLogsRequestParams.projector(
id,
keywords
);

expect(params).toEqual({
id,
startDate: '1970-01-01T00:00:00.000',
endDate: '1970-01-01T00:00:00.000',
sort: 'timestamp'
})
});

it('should select load logs request params with keywords', () => {
const id = 'test-id';
const keywords = [
{ text: 'test-keyword1' },
{ text: 'test-keyword2' }
];

const params = loadVmLogsRequestParams.projector(
id,
keywords
);

expect(params).toEqual({
id,
keywords: 'test-keyword1,test-keyword2',
startDate: '1970-01-01T00:00:00.000',
endDate: '1970-01-01T00:00:00.000',
sort: 'timestamp'
});
});

const defaultId = 'test-id';
const defaultDate = '1970-01-01T00:00:00.000';
const defaultSort = 'timestamp';
const defaultRequestParams = {
id: defaultId,
startDate: defaultDate,
endDate: defaultDate,
sort: defaultSort
};

it('should set sort: -timestamp if newest first = true', () => {
const id = 'test-id';

const params = loadVmLogsRequestParams.projector(
id,
[],
date,
date,
'',
true
);

expect(params).toEqual({
...defaultRequestParams,
sort: '-timestamp'
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createSelector } from '@ngrx/store';
import { filterSelectedVmId } from '../vm-logs-vm.reducers';
import { LoadVmLogsRequestParams } from '../../models/load-vm-logs-request-params';
import {
filterEndDate,
filterKeywords,
filterNewestFirst,
filterSelectedLogFile,
filterStartDate
} from '../vm-logs.reducers';
import moment = require('moment');
import * as pickBy from 'lodash/pickBy';


export const loadVmLogsRequestParams = createSelector(
filterSelectedVmId,
filterKeywords,
filterStartDate,
filterEndDate,
filterSelectedLogFile,
filterNewestFirst,
(id, keywords, startDate, endDate, logFile, newestFirst): LoadVmLogsRequestParams => {
const fields = {
id,
keywords: keywords.map(keyword => keyword.text).join(','),
startDate: moment(startDate).toISOString().slice(0, -1),
endDate: moment(endDate).toISOString().slice(0, -1),
sort: newestFirst ? '-timestamp' : 'timestamp',
logFile,
};

return pickBy(fields, Boolean);
}
);

Loading

0 comments on commit 6953691

Please sign in to comment.