AMBARI-21699 Log Search UI: implement histogram for service logs. (ababiichuk)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/af5f5d23 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/af5f5d23 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/af5f5d23 Branch: refs/heads/branch-feature-logsearch-ui Commit: af5f5d23d29f97344cb44085d649a702d02f1882 Parents: 0256fb7 Author: ababiichuk <ababiic...@hortonworks.com> Authored: Thu Aug 10 13:22:25 2017 +0300 Committer: ababiichuk <ababiic...@hortonworks.com> Committed: Thu Aug 10 13:22:25 2017 +0300 ---------------------------------------------------------------------- .../ambari-logsearch-web-new/package.json | 3 + .../src/app/app.module.ts | 10 +- ...service-logs-histogram-query-params.class.ts | 33 ++ .../logs-container.component.html | 19 + .../logs-container.component.less | 25 ++ .../logs-container.component.spec.ts | 84 ++++ .../logs-container/logs-container.component.ts | 160 +++++++ .../logs-list/logs-list.component.html | 10 +- .../logs-list/logs-list.component.less | 176 ++++---- .../components/logs-list/logs-list.component.ts | 80 +--- .../main-container.component.html | 2 +- .../time-histogram.component.html | 18 + .../time-histogram.component.less | 29 ++ .../time-histogram.component.spec.ts | 53 +++ .../time-histogram/time-histogram.component.ts | 161 ++++++++ .../src/app/mock-data.ts | 22 +- .../src/app/models/store.model.ts | 2 +- .../src/app/services/filtering.service.ts | 82 ++-- .../src/app/services/http-client.service.ts | 5 + .../app/services/storage/bar-graphs.service.ts | 32 -- .../app/services/storage/reducers.service.ts | 4 +- .../service-logs-histogram-data.service.ts | 32 ++ .../services/storage/service-logs.service.ts | 1 - .../ambari-logsearch-web-new/yarn.lock | 412 ++++++++++++++++++- 24 files changed, 1190 insertions(+), 265 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/package.json ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/package.json b/ambari-logsearch/ambari-logsearch-web-new/package.json index 847787b..b4902a3 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/package.json +++ b/ambari-logsearch/ambari-logsearch-web-new/package.json @@ -27,6 +27,7 @@ "angular2-moment": "^1.4.0", "bootstrap": "^3.3.7", "core-js": "^2.4.1", + "d3": "^4.10.0", "font-awesome": "^4.7.0", "jquery": "^1.12.4", "moment": "^2.18.1", @@ -38,7 +39,9 @@ "devDependencies": { "@angular/cli": "1.0.0", "@angular/compiler-cli": "^4.0.0", + "@types/d3": "^4.10.0", "@types/jasmine": "2.5.38", + "@types/jquery": "^1.10.33", "@types/moment": "^2.13.0", "@types/moment-timezone": "^0.2.34", "@types/node": "~6.0.60", http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts index 503aa46..f81e75b 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts @@ -38,7 +38,7 @@ import {AppSettingsService} from '@app/services/storage/app-settings.service'; import {AppStateService} from '@app/services/storage/app-state.service'; import {AuditLogsService} from '@app/services/storage/audit-logs.service'; import {ServiceLogsService} from '@app/services/storage/service-logs.service'; -import {BarGraphsService} from '@app/services/storage/bar-graphs.service'; +import {ServiceLogsHistogramDataService} from '@app/services/storage/service-logs-histogram-data.service'; import {GraphsService} from '@app/services/storage/graphs.service'; import {NodesService} from '@app/services/storage/nodes.service'; import {UserConfigsService} from '@app/services/storage/user-configs.service'; @@ -62,6 +62,8 @@ import {LogsListComponent} from '@app/components/logs-list/logs-list.component'; import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component'; import {PaginationComponent} from '@app/components/pagination/pagination.component'; import {PaginationControlsComponent} from '@app/components/pagination-controls/pagination-controls.component'; +import {TimeHistogramComponent} from '@app/components/time-histogram/time-histogram.component'; +import {LogsContainerComponent} from '@app/components/logs-container/logs-container.component'; export function HttpLoaderFactory(http: Http) { // adding 'static' parameter to step over mock data request @@ -99,7 +101,9 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR LogsListComponent, DropdownButtonComponent, PaginationComponent, - PaginationControlsComponent + PaginationControlsComponent, + TimeHistogramComponent, + LogsContainerComponent ], imports: [ BrowserModule, @@ -127,7 +131,7 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR AppStateService, AuditLogsService, ServiceLogsService, - BarGraphsService, + ServiceLogsHistogramDataService, GraphsService, NodesService, UserConfigsService, http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/service-logs-histogram-query-params.class.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/service-logs-histogram-query-params.class.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/service-logs-histogram-query-params.class.ts new file mode 100644 index 0000000..bbb520a --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/classes/queries/service-logs-histogram-query-params.class.ts @@ -0,0 +1,33 @@ +/** + * 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 {QueryParams} from '@app/classes/queries/query-params.class'; + +export const defaultParams = { + unit: '+1HOUR' +}; + +export class ServiceLogsHistogramQueryParams extends QueryParams { + constructor(options: ServiceLogsHistogramQueryParams) { + const finalParams = Object.assign({}, defaultParams, options); + super(finalParams); + } + from: string; + to: string; + unit?: string; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html new file mode 100644 index 0000000..a7dabe8 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.html @@ -0,0 +1,19 @@ +<!-- + 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. +--> + +<time-histogram class="col-md-12" [data]="histogramData" [customOptions]="histogramOptions"></time-histogram> +<logs-list [logs]="logs | async" [totalCount]="totalCount"></logs-list> http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.less new file mode 100644 index 0000000..60082d6 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.less @@ -0,0 +1,25 @@ +/** + * 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 '../variables'; + +:host { + display: block; + overflow: hidden; + padding-top: @block-margin-top; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts new file mode 100644 index 0000000..7792fa9 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.spec.ts @@ -0,0 +1,84 @@ +/** + * 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 {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import {StoreModule} from '@ngrx/store'; +import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service'; +import {ClustersService, clusters} from '@app/services/storage/clusters.service'; +import {ComponentsService, components} from '@app/services/storage/components.service'; +import {ServiceLogsService, serviceLogs} from '@app/services/storage/service-logs.service'; +import {ServiceLogsHistogramDataService, serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service'; +import {HttpClientService} from '@app/services/http-client.service'; +import {FilteringService} from '@app/services/filtering.service'; +import {UtilsService} from '@app/services/utils.service'; + +import {LogsContainerComponent} from './logs-container.component'; + +describe('LogsContainerComponent', () => { + const httpClient = { + get: () => { + return { + subscribe: () => { + } + }; + } + }; + let component: LogsContainerComponent; + let fixture: ComponentFixture<LogsContainerComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [LogsContainerComponent], + imports: [ + StoreModule.provideStore({ + appSettings, + clusters, + components, + serviceLogs, + serviceLogsHistogramData + }) + ], + providers: [ + { + provide: HttpClientService, + useValue: httpClient + }, + AppSettingsService, + ClustersService, + ComponentsService, + ServiceLogsService, + ServiceLogsHistogramDataService, + FilteringService, + UtilsService + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LogsContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create component', () => { + expect(component).toBeTruthy(); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts new file mode 100644 index 0000000..5823846 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-container/logs-container.component.ts @@ -0,0 +1,160 @@ +/** + * 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, OnInit, Input} from '@angular/core'; +import {FormGroup} from '@angular/forms'; +import 'rxjs/add/operator/map'; +import {HttpClientService} from '@app/services/http-client.service'; +import {FilteringService} from '@app/services/filtering.service'; +import {ServiceLogsService} from '@app/services/storage/service-logs.service'; +import {ServiceLogsHistogramDataService} from '@app/services/storage/service-logs-histogram-data.service'; + +@Component({ + selector: 'logs-container', + templateUrl: './logs-container.component.html', + styleUrls: ['./logs-container.component.less'] +}) +export class LogsContainerComponent implements OnInit { + + constructor(private httpClient: HttpClientService, private serviceLogsStorage: ServiceLogsService, private serviceLogsHistogramStorage: ServiceLogsHistogramDataService, private filtering: FilteringService) { + this.serviceLogsHistogramStorage.getAll().subscribe(data => { + let histogramData = {}; + data.forEach(type => { + const name = type.name; + type.dataCount.forEach(entry => { + const timeStamp = new Date(entry.name).valueOf(); + if (!histogramData[timeStamp]) { + let initialValue = {}; + Object.keys(this.histogramOptions.keysWithColors).forEach(key => initialValue[key] = 0); + histogramData[timeStamp] = initialValue; + } + histogramData[timeStamp][name] = Number(entry.value); + }); + }); + this.histogramData = histogramData; + }); + } + + ngOnInit() { + this.loadLogs(); + this.filtersForm.valueChanges.subscribe(() => { + this.loadLogs(); + }); + } + + @Input() + private logsArrayId: string; + + totalCount: number = 0; + + private readonly listFilters = { + clusters: ['clusters'], + text: ['iMessage'], + timeRange: ['end_time', 'start_time'], + components: ['component_name'], + levels: ['level'], + sorting: ['sortType', 'sortBy'], + pageSize: ['pageSize'], + page: ['page'] + }; + + private readonly histogramFilters = { + timeRange: ['to', 'from'] + }; + + logs = this.serviceLogsStorage.getAll().map(logs => logs.map(log => { + return { + type: log.type, + level: log.level, + className: log.level.toLowerCase(), + message: log.log_message, + time: log.logtime + }; + })); + + histogramData: any; + + readonly histogramOptions = { + keysWithColors: { + WARN: '#FF8916', + ERROR: '#E81D1D', + FATAL: '#830A0A', + INFO: '#2577B5', + DEBUG: '#65E8FF', + TRACE: '#888', + UNKNOWN: '#BDBDBD' + } + }; + + private get filtersForm(): FormGroup { + return this.filtering.filtersForm; + } + + private loadLogs(): void { + this.httpClient.get(this.logsArrayId, this.getParams('listFilters')).subscribe(response => { + const jsonResponse = response.json(); + this.serviceLogsStorage.clear(); + if (jsonResponse) { + const logs = jsonResponse.logList, + count = jsonResponse.totalCount || 0; + if (logs) { + this.serviceLogsStorage.addInstances(logs); + } + this.totalCount = count; + } + }); + this.httpClient.get('serviceLogsHistogram', this.getParams('histogramFilters')).subscribe(response => { + const jsonResponse = response.json(); + this.serviceLogsHistogramStorage.clear(); + if (jsonResponse) { + const histogramData = jsonResponse.graphData; + if (histogramData) { + this.serviceLogsHistogramStorage.addInstances(histogramData); + } + } + }); + } + + private getParams(filtersMapName: string): any { + let params = {}; + Object.keys(this[filtersMapName]).forEach(key => { + const inputValue = this.filtersForm.getRawValue()[key], + paramNames = this[filtersMapName][key]; + paramNames.forEach(paramName => { + let value; + const valueGetter = this.filtering.valueGetters[paramName]; + if (valueGetter) { + if (paramName === 'start_time') { + value = valueGetter(inputValue, params['end_time']); + } else if (paramName === 'from') { + value = valueGetter(inputValue, params['to']); + } else { + value = valueGetter(inputValue); + } + } else { + value = inputValue; + } + if (value != null && value !== '') { + params[paramName] = value; + } + }); + }, this); + return params; + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html index 4c84b9c..e9b3c67 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html @@ -15,17 +15,17 @@ limitations under the License. --> -<form *ngIf="(logs | async).length" [formGroup]="filtersForm"> +<form *ngIf="logs.length" [formGroup]="filtersForm" class="pull-right"> <filter-dropdown [label]="filters.sorting.label" formControlName="sorting" [options]="filters.sorting.options" [defaultLabel]="filters.sorting.defaultLabel" isRightAlign="true"></filter-dropdown> </form> -<div class="col-md-12 text-center" *ngIf="(logs | async).length"> +<div class="col-md-12 text-center" *ngIf="logs.length"> <div class="logs-header"> <div class="col-md-1">{{'logs.status' | translate}}</div> <div class="col-md-11">{{'logs.details' | translate}}</div> </div> </div> -<accordion-panel *ngFor="let log of logs | async; let i = index" [toggleId]="'details-' + i" class="col-md-12"> +<accordion-panel *ngFor="let log of logs; let i = index" [toggleId]="'details-' + i" class="col-md-12"> <ng-template> <div [ngClass]="'hexagon ' + log.className"></div> <div [ngClass]="'col-md-1 log-status ' + log.className">{{log.level}}</div> @@ -43,5 +43,5 @@ </div> </ng-template> </accordion-panel> -<pagination class="col-md-12" *ngIf="(logs | async).length" [totalCount]="totalCount" [filtersForm]="filtersForm" - [filterInstance]="filters.pageSize" [currentCount]="(logs | async).length"></pagination> +<pagination class="col-md-12" *ngIf="logs.length" [totalCount]="totalCount" [filtersForm]="filtersForm" + [filterInstance]="filters.pageSize" [currentCount]="logs.length"></pagination> http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less index 76c16a5..63c0354 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less @@ -17,125 +17,119 @@ @import '../variables'; -:host { - display: block; +.logs-header { + // TODO get rid of magic numbers, base on actual design + margin: 10px 0; + padding: 5px 0; + background-color: @list-header-background-color; // TODO implement actual color overflow: hidden; - padding-top: @block-margin-top; + text-transform: uppercase; +} - .logs-header { - // TODO get rid of magic numbers, base on actual design - margin: 10px 0; - padding: 5px 0; - background-color: @list-header-background-color; // TODO implement actual color - overflow: hidden; - text-transform: uppercase; - } +/deep/ filter-dropdown { + justify-content: flex-end; +} + +.hexagon { + // TODO get rid of magic numbers, base on actual design + left: -7.5px; - /deep/ filter-dropdown { - justify-content: flex-end; + &.fatal { + .common-hexagon(15px, @fatal-color); } - .hexagon { - // TODO get rid of magic numbers, base on actual design - left: -7.5px; + &.error { + .common-hexagon(15px, @error-color); + } - &.fatal { - .common-hexagon(15px, @fatal-color); - } + &.warn { + .common-hexagon(15px, @warning-color); + } - &.error { - .common-hexagon(15px, @error-color); - } + &.info { + .common-hexagon(15px, @info-color); + } - &.warn { - .common-hexagon(15px, @warning-color); - } + &.debug { + .common-hexagon(15px, @debug-color); + } - &.info { - .common-hexagon(15px, @info-color); - } + &.trace { + .common-hexagon(15px, @trace-color); + } - &.debug { - .common-hexagon(15px, @debug-color); - } + &.unknown { + .common-hexagon(15px, @unknown-color); + } +} - &.trace { - .common-hexagon(15px, @trace-color); - } +.log-status { + text-transform: uppercase; - &.unknown { - .common-hexagon(15px, @unknown-color); - } + &.fatal { + color: @fatal-color; } - .log-status { - text-transform: uppercase; + &.error { + color: @error-color; + } - &.fatal { - color: @fatal-color; - } + &.warn { + color: @warning-color; + } - &.error { - color: @error-color; - } + &.info { + color: @info-color; + } - &.warn { - color: @warning-color; - } + &.debug { + color: @debug-color; + } - &.info { - color: @info-color; - } + &.trace { + color: @trace-color; + } - &.debug { - color: @debug-color; - } + &.unknown { + color: @unknown-color; + } +} - &.trace { - color: @trace-color; - } +.log-type { + color: @link-color; +} - &.unknown { - color: @unknown-color; - } - } +.log-time { + color: @grey-color; +} - .log-type { - color: @link-color; - } +.log-content-wrapper { + position: relative; - .log-time { - color: @grey-color; + // TODO get rid of magic numbers, base on actual design + .log-content { + overflow: hidden; + max-height: @default-line-height * 2em; + padding-right: 65px; + white-space: pre-wrap; } - .log-content-wrapper { - position: relative; + .log-actions { + position: absolute; + right: 40px; + top: 0; + border: @input-border; - // TODO get rid of magic numbers, base on actual design - .log-content { - overflow: hidden; - max-height: @default-line-height * 2em; - padding-right: 65px; - white-space: pre-wrap; + &.collapsing + .log-content, &.collapse.in + .log-content { + min-height: 6em; + max-height: none; + overflow-x: auto; } - .log-actions { - position: absolute; - right: 40px; - top: 0; - border: @input-border; - - &.collapsing + .log-content, &.collapse.in + .log-content { - min-height: 6em; - max-height: none; - overflow-x: auto; - } - - .action-icon { - .clickable-item; - display: block; - padding: 5px; - } + .action-icon { + .clickable-item; + display: block; + padding: 5px; } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts index 7427fc1..27b5021 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts @@ -15,11 +15,9 @@ * limitations under the License. */ -import {Component, OnInit, Input} from '@angular/core'; +import {Component, Input} from '@angular/core'; import {FormGroup} from '@angular/forms'; import 'rxjs/add/operator/map'; -import {HttpClientService} from '@app/services/http-client.service'; -import {ServiceLogsService} from '@app/services/storage/service-logs.service'; import {FilteringService} from '@app/services/filtering.service'; @Component({ @@ -27,46 +25,19 @@ import {FilteringService} from '@app/services/filtering.service'; templateUrl: './logs-list.component.html', styleUrls: ['./logs-list.component.less'] }) -export class LogsListComponent implements OnInit { +export class LogsListComponent { - constructor(private httpClient: HttpClientService, private serviceLogsStorage: ServiceLogsService, private filtering: FilteringService) { - } - - ngOnInit() { - this.loadLogs(); - this.filtersForm.valueChanges.subscribe(() => { - this.loadLogs(); - }); + constructor(private filtering: FilteringService) { } @Input() - private logsArrayId: string; + logs: any[] = []; + @Input() totalCount: number = 0; timeFormat: string = 'DD/MM/YYYY HH:mm:ss'; - private readonly usedFilters = { - clusters: ['clusters'], - text: ['iMessage'], - timeRange: ['end_time', 'start_time'], - components: ['component_name'], - levels: ['level'], - sorting: ['sortType', 'sortBy'], - pageSize: ['pageSize'], - page: ['page'] - }; - - logs = this.serviceLogsStorage.getAll().map(logs => logs.map(log => { - return { - type: log.type, - level: log.level, - className: log.level.toLowerCase(), - message: log.log_message, - time: log.logtime - }; - })); - get timeZone(): string { return this.filtering.timeZone; } @@ -79,45 +50,4 @@ export class LogsListComponent implements OnInit { return this.filtering.filtersForm; } - private loadLogs(): void { - this.httpClient.get(this.logsArrayId, this.getParams()).subscribe(response => { - const jsonResponse = response.json(); - this.serviceLogsStorage.clear(); - if (jsonResponse) { - const logs = jsonResponse.logList, - count = jsonResponse.totalCount || 0; - if (logs) { - const logs = response.json().logList; - this.serviceLogsStorage.addInstances(logs); - } - this.totalCount = count; - } - }); - } - - private getParams(): any { - let params = {}; - Object.keys(this.usedFilters).forEach(key => { - const inputValue = this.filtersForm.getRawValue()[key], - paramNames = this.usedFilters[key]; - paramNames.forEach(paramName => { - let value; - const valueGetter = this.filtering.valueGetters[paramName]; - if (valueGetter) { - if (paramName === 'start_time') { - value = valueGetter(inputValue, params['end_time']); - } else { - value = valueGetter(inputValue); - } - } else { - value = inputValue; - } - if (value != null && value !== '') { - params[paramName] = value; - } - }); - }, this); - return params; - } - } http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html index 42a8fbf..f4cf47a 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/main-container/main-container.component.html @@ -21,4 +21,4 @@ </div> <login-form *ngIf="!isInitialLoading && !isAuthorized"></login-form> <filters-panel *ngIf="isAuthorized" class="row"></filters-panel> -<logs-list *ngIf="isAuthorized" [logsArrayId]="'serviceLogs'"></logs-list> +<logs-container *ngIf="isAuthorized" logsArrayId="serviceLogs"></logs-container> http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.html new file mode 100644 index 0000000..299e46e --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.html @@ -0,0 +1,18 @@ +<!-- + 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. +--> + +<div #container></div> http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.less new file mode 100644 index 0000000..58882ff --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.less @@ -0,0 +1,29 @@ +/** + * 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. + */ + +/deep/ .axis { + .domain { + display: none; + } + + .tick { + line { + display: none; + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.spec.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.spec.ts new file mode 100644 index 0000000..d2f6e3a --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.spec.ts @@ -0,0 +1,53 @@ +/** + * 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 {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {StoreModule} from '@ngrx/store'; +import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service'; + +import {TimeHistogramComponent} from './time-histogram.component'; + +describe('TimeHistogramComponent', () => { + let component: TimeHistogramComponent; + let fixture: ComponentFixture<TimeHistogramComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TimeHistogramComponent], + imports: [ + StoreModule.provideStore({ + appSettings + }) + ], + providers: [ + AppSettingsService + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TimeHistogramComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create component', () => { + expect(component).toBeTruthy(); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts new file mode 100644 index 0000000..485c4cc --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/time-histogram/time-histogram.component.ts @@ -0,0 +1,161 @@ +/** + * 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, OnInit, AfterViewInit, OnChanges, Input, ViewChild, ElementRef} from '@angular/core'; +import * as d3 from 'd3'; +import * as moment from 'moment-timezone'; +import {AppSettingsService} from '@app/services/storage/app-settings.service'; + +@Component({ + selector: 'time-histogram', + templateUrl: './time-histogram.component.html', + styleUrls: ['./time-histogram.component.less'] +}) +export class TimeHistogramComponent implements OnInit, AfterViewInit, OnChanges { + + constructor(private appSettings: AppSettingsService) { + this.appSettings.getParameter('timeZone').subscribe(value => { + this.timeZone = value; + this.createHistogram(); + }); + } + + ngOnInit() { + Object.assign(this.options, this.defaultOptions, this.customOptions); + } + + ngAfterViewInit() { + this.htmlElement = this.element.nativeElement; + this.host = d3.select(this.htmlElement); + } + + ngOnChanges() { + this.createHistogram(); + } + + @ViewChild('container') + element: ElementRef; + + @Input() + customOptions: any; + + @Input() + data: any; + + private readonly defaultOptions = { + margin: { + top: 20, + right: 20, + bottom: 40, + left: 50 + }, + height: 200, + tickPadding: 10, + columnWidth: 20 + }; + + private options: any = {}; + + private timeZone: string; + + private host; + + private svg; + + private width; + + private xScale; + + private yScale; + + private colorScale; + + private xAxis; + + private yAxis; + + private htmlElement: HTMLElement; + + histogram: any; + + private createHistogram(): void { + if (this.host) { + this.setup(); + this.buildSVG(); + this.populate(); + } + } + + private setup(): void { + const margin = this.options.margin, + keysWithColors = this.options.keysWithColors, + keys = Object.keys(keysWithColors), + colors = keys.reduce((array, key) => [...array, keysWithColors[key]], []); + this.width = this.htmlElement.clientWidth - margin.left - margin.right; + this.xScale = d3.scaleTime().range([0, this.width]); + this.yScale = d3.scaleLinear().range([this.options.height, 0]); + this.colorScale = d3.scaleOrdinal(colors); + } + + private buildSVG(): void { + const margin = this.options.margin; + this.host.html(''); + this.svg = this.host.append('svg').attr('width', this.width + margin.left + margin.right) + .attr('height', this.options.height + margin.top + margin.bottom).append('g') + .attr('transform', `translate(${margin.left},${margin.top})`); + } + + private drawXAxis(): void { + this.xAxis = d3.axisBottom(this.xScale) + .tickFormat(tick => moment(tick).tz(this.timeZone).format('MM/DD HH:mm')) + .tickPadding(this.options.tickPadding); + this.svg.append('g').attr('class', 'axis').attr('transform', `translate(0,${this.options.height})`).call(this.xAxis); + } + + private drawYAxis(): void { + this.yAxis = d3.axisLeft(this.yScale).tickFormat((tick: number) => { + if (Number.isInteger(tick)) { + return tick.toFixed(0); + } else { + return; + } + }).tickPadding(this.options.tickPadding); + this.svg.append('g').attr('class', 'axis').call(this.yAxis).append('text'); + } + + private populate(): void { + const keys = Object.keys(this.options.keysWithColors), + data = this.data, + timeStamps = Object.keys(data), + formattedData = timeStamps.map(timeStamp => Object.assign({ + timeStamp: timeStamp + }, data[timeStamp])), + layers = (d3.stack().keys(keys)(formattedData)), + columnWidth = this.options.columnWidth; + this.xScale.domain(d3.extent(formattedData, item => item.timeStamp)); + this.yScale.domain([0, d3.max(formattedData, item => keys.reduce((sum, key) => sum + item[key], 0))]); + this.drawXAxis(); + this.drawYAxis(); + const layer = this.svg.selectAll().data(d3.transpose<any>(layers)).enter().append('g'); + layer.selectAll().data(item => item).enter().append('rect') + .attr('x', item => this.xScale(item.data.timeStamp) - columnWidth / 2).attr('y', item => this.yScale(item[1])) + .attr('height', item => this.yScale(item[0]) - this.yScale(item[1])).attr('width', columnWidth.toString()) + .style('fill', (item, index) => this.colorScale(index)); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts index 3d04122..ecac362 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/mock-data.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import * as moment from 'moment-timezone'; +import * as moment from 'moment'; export const mockData = { login: {}, @@ -564,28 +564,28 @@ export const mockData = { { dataCount: [ { - name: 'n12', - value: 1000 + name: moment().toISOString(), + value: '1000' }, { - name: 'n13', - value: 2000 + name: moment().add(1, 'h').toISOString(), + value: '2000' } ], - name: 'graph6' + name: 'ERROR' }, { dataCount: [ { - name: 'n14', - value: 700 + name: moment().toISOString(), + value: '700' }, { - name: 'n15', - value: 900 + name: moment().add(1, 'h').toISOString(), + value: '900' } ], - name: 'graph7' + name: 'WARN' } ] }, http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts index 190ab7e..fce72d7 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/models/store.model.ts @@ -42,7 +42,7 @@ export interface AppStore { appState: AppState; auditLogs: AuditLog[]; serviceLogs: ServiceLog[]; - barGraphs: BarGraph[]; + serviceLogsHistogramData: BarGraph[]; graphs: Graph[]; nodes: Node[]; userConfigs: UserConfig[]; http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts index c317076..009b263 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts @@ -276,46 +276,52 @@ export class FilteringService { filtersForm = new FormGroup(this.filtersFormItems); - readonly valueGetters = { - end_time: value => { - let time; - if (value) { - switch (value.type) { - case 'LAST': - time = moment(); - break; - case 'CURRENT': - time = moment().tz(this.timeZone).endOf(value.unit); - break; - case 'PAST': - time = moment().tz(this.timeZone).startOf(value.unit).millisecond(-1); - break; - default: - break; - } + private getStartTime(value: any, current: string): string { + let time; + if (value) { + const endTime = moment(moment(current).valueOf()); + switch (value.type) { + case 'LAST': + time = endTime.subtract(value.interval, value.unit); + break; + case 'CURRENT': + time = moment().tz(this.timeZone).startOf(value.unit); + break; + case 'PAST': + time = endTime.startOf(value.unit); + break; + default: + break; } - return time ? time.toISOString() : ''; - }, - start_time: (value, current) => { - let time; - if (value) { - const endTime = moment(moment(current).valueOf()); - switch (value.type) { - case 'LAST': - time = endTime.subtract(value.interval, value.unit); - break; - case 'CURRENT': - time = moment().tz(this.timeZone).startOf(value.unit); - break; - case 'PAST': - time = endTime.startOf(value.unit); - break; - default: - break; - } + } + return time ? time.toISOString() : ''; + } + + private getEndTime(value: any): string { + let time; + if (value) { + switch (value.type) { + case 'LAST': + time = moment(); + break; + case 'CURRENT': + time = moment().tz(this.timeZone).endOf(value.unit); + break; + case 'PAST': + time = moment().tz(this.timeZone).startOf(value.unit).millisecond(-1); + break; + default: + break; } - return time ? time.toISOString() : ''; - }, + } + return time ? time.toISOString() : ''; + } + + readonly valueGetters = { + end_time: this.getEndTime.bind(this), + start_time: this.getStartTime.bind(this), + to: this.getEndTime.bind(this), + from: this.getStartTime.bind(this), sortType: value => value && value.type, sortBy: value => value && value.key, page: value => value == null ? value : value.toString() http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts index 0d06899..260b920 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/http-client.service.ts @@ -22,6 +22,7 @@ import 'rxjs/add/operator/first'; import {Http, XHRBackend, Request, RequestOptions, RequestOptionsArgs, Response, Headers, URLSearchParams} from '@angular/http'; import {AuditLogsQueryParams} from '@app/classes/queries/audit-logs-query-params.class'; import {ServiceLogsQueryParams} from '@app/classes/queries/service-logs-query-params.class'; +import {ServiceLogsHistogramQueryParams} from '@app/classes/queries/service-logs-histogram-query-params.class'; import {AppStateService} from '@app/services/storage/app-state.service'; @Injectable() @@ -45,6 +46,10 @@ export class HttpClientService extends Http { url: 'service/logs', params: opts => new ServiceLogsQueryParams(opts) }, + serviceLogsHistogram: { + url: 'service/logs/histogram', + params: opts => new ServiceLogsHistogramQueryParams(opts) + }, components: { url: 'service/logs/components' }, http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts deleted file mode 100644 index e9a3cb7..0000000 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/bar-graphs.service.ts +++ /dev/null @@ -1,32 +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 {Injectable} from '@angular/core'; -import {Store} from '@ngrx/store'; -import {AppStore, CollectionModelService, getCollectionReducer} from '@app/models/store.model'; - -export const modelName = 'barGraphs'; - -@Injectable() -export class BarGraphsService extends CollectionModelService { - constructor(store: Store<AppStore>) { - super(modelName, store); - } -} - -export const barGraphs = getCollectionReducer(modelName); http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts index 6665901..3c92c75 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/reducers.service.ts @@ -20,13 +20,13 @@ import {combineReducers} from '@ngrx/store'; import {appSettings} from '@app/services/storage/app-settings.service'; import {appState} from '@app/services/storage/app-state.service'; import {auditLogs} from '@app/services/storage/audit-logs.service'; -import {barGraphs} from '@app/services/storage/bar-graphs.service'; import {clusters} from '@app/services/storage/clusters.service'; import {components} from '@app/services/storage/components.service'; import {filters} from '@app/services/storage/filters.service'; import {graphs} from '@app/services/storage/graphs.service'; import {nodes} from '@app/services/storage/nodes.service'; import {serviceLogs} from '@app/services/storage/service-logs.service'; +import {serviceLogsHistogramData} from '@app/services/storage/service-logs-histogram-data.service'; import {userConfigs} from '@app/services/storage/user-configs.service'; export const reducers = { @@ -34,7 +34,7 @@ export const reducers = { appState, auditLogs, serviceLogs, - barGraphs, + serviceLogsHistogramData, graphs, nodes, userConfigs, http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs-histogram-data.service.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs-histogram-data.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs-histogram-data.service.ts new file mode 100644 index 0000000..0573247 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs-histogram-data.service.ts @@ -0,0 +1,32 @@ +/** + * 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 {Injectable} from '@angular/core'; +import {Store} from '@ngrx/store'; +import {AppStore, CollectionModelService, getCollectionReducer} from '@app/models/store.model'; + +export const modelName = 'serviceLogsHistogramData'; + +@Injectable() +export class ServiceLogsHistogramDataService extends CollectionModelService { + constructor(store: Store<AppStore>) { + super(modelName, store); + } +} + +export const serviceLogsHistogramData = getCollectionReducer(modelName); http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts index 24c3776..529a390 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts +++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/storage/service-logs.service.ts @@ -16,7 +16,6 @@ * limitations under the License. */ - import {Injectable} from '@angular/core'; import {Store} from '@ngrx/store'; import {AppStore, CollectionModelService, getCollectionReducer} from '@app/models/store.model'; http://git-wip-us.apache.org/repos/asf/ambari/blob/af5f5d23/ambari-logsearch/ambari-logsearch-web-new/yarn.lock ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web-new/yarn.lock b/ambari-logsearch/ambari-logsearch-web-new/yarn.lock index 6e592a7..291b489 100644 --- a/ambari-logsearch/ambari-logsearch-web-new/yarn.lock +++ b/ambari-logsearch/ambari-logsearch-web-new/yarn.lock @@ -141,10 +141,194 @@ version "0.0.3" resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-0.0.3.tgz#8346c8d2d6f630254601029668f17abe2afe8a9b" +"@types/d3-array@*": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.0.tgz#9b1fc3202fc1a9f7da0f2873bd38b443137a9d34" + +"@types/d3-axis@*": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-1.0.9.tgz#62ce7bc8d04354298cda57f3f1d1f856ad69b89a" + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-1.0.7.tgz#05c30440f4d537fd23f976b0e6c4ba223001ef45" + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-1.0.6.tgz#0589eb97a3191f4edaf17b7bde498462890ce1ec" + +"@types/d3-collection@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-collection/-/d3-collection-1.0.5.tgz#bb1f3aa97cdc8d881645541b9d6cf87edfee9bc3" + +"@types/d3-color@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-1.0.5.tgz#cad755f0fc6de7b70fa6e5e08afa81ef4c2248de" + +"@types/d3-dispatch@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-1.0.5.tgz#f1f9187b538ecb05157569d8dc2f70dfb04f1b52" + +"@types/d3-drag@*": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-1.1.0.tgz#9105e35ca58aa0c4783f3ce83082bcb24ccb6960" + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "1.0.30" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-1.0.30.tgz#78e0dddde4283566f463e51551a97a63c170d5a8" + +"@types/d3-ease@*": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-1.0.7.tgz#93a301868be9e15061f3d44343b1ab3f8acb6f09" + +"@types/d3-force@*": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-1.0.7.tgz#8e3c533697143ebb70275d56840206e8ba789185" + +"@types/d3-format@*": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-1.2.0.tgz#3e128efc9e6dd09df8fd21f1d981ab68e140a8a2" + +"@types/d3-geo@*": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-1.6.3.tgz#21b501d1fe224d88877f39f84cb8c9dd8aa1bf28" + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-1.1.0.tgz#50f1ee052840638035cbdd4acab1fc3470905907" + +"@types/d3-interpolate@*": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-1.1.6.tgz#64041b15c9c032c348da1b22baabc59fa4d16136" + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.6.tgz#c1a7d2dc07b295fdd1c84dabe4404df991b48693" + +"@types/d3-polygon@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-1.0.5.tgz#35ad54ed84c39d7e9f1252b6535be600be6cace2" + +"@types/d3-quadtree@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-1.0.5.tgz#1ce1e659eae4530df0cb127f297f1741a367a82e" + +"@types/d3-queue@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-queue/-/d3-queue-3.0.5.tgz#3e4cbe2aff61db6a0b2b8c4800299e4ec6acc850" + +"@types/d3-random@*": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-1.1.0.tgz#2dd08f1159c70719270e4a7c834af85c8b88d2c3" + +"@types/d3-request@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-request/-/d3-request-1.0.2.tgz#db9db8154f47816584706c6e6f702be66f22f4be" + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-scale@*": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-1.0.10.tgz#8c5c1dca54a159eed042b46719dbb3bdb7e8c842" + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-1.1.0.tgz#59b88f10d2cff7d9ffd7fe986b3aaef3de048224" + +"@types/d3-shape@*": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.2.1.tgz#cac2d9f0122f173220c32c8c152dc42ee9349df2" + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-2.0.5.tgz#1d4c5ba77ed5352b10c7fce062c883382f1e16e0" + +"@types/d3-time@*": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-1.0.7.tgz#4266d7c9be15fa81256a88d1d052d61cd8dc572c" + +"@types/d3-timer@*": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-1.0.6.tgz#786d4e20731adf03af2c5df6c86fe29667fe429b" + +"@types/d3-transition@*": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-1.1.0.tgz#74475d4a8f8a0944a517d5ef861970cc30287e40" + dependencies: + "@types/d3-selection" "*" + +"@types/d3-voronoi@*": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-voronoi/-/d3-voronoi-1.1.6.tgz#b52252c1d61972e7c751135890aea112d5dadc6d" + +"@types/d3-zoom@*": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-1.5.0.tgz#21f690b25a8419fd1bcc95ac629cefdfb462c70f" + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^4.10.0": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-4.10.0.tgz#721d8f984ba4bc192b1c1aca3834b31cc31fa9d3" + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-collection" "*" + "@types/d3-color" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-queue" "*" + "@types/d3-random" "*" + "@types/d3-request" "*" + "@types/d3-scale" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-voronoi" "*" + "@types/d3-zoom" "*" + +"@types/geojson@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03" + "@types/jasmine@2.5.38": version "2.5.38" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.38.tgz#a4379124c4921d4e21de54ec74669c9e9b356717" +"@types/jquery@^1.10.33": + version "1.10.33" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-1.10.33.tgz#6c4c279f8d06839b184950432e880e0a469a64a1" + "@types/moment-timezone@^0.2.34": version "0.2.34" resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.2.34.tgz#948e0aff82742a31dd63714d1aac9616bc375053" @@ -956,7 +1140,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2.9.x, commander@~2.9.0: +commander@2, commander@2.9.x, commander@~2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: @@ -1253,6 +1437,216 @@ custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" +d3-array@1, d3-array@1.2.0, d3-array@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.0.tgz#147d269720e174c4057a7f42be8b0f3f2ba53108" + +d3-axis@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.8.tgz#31a705a0b535e65759de14173a31933137f18efa" + +d3-brush@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.4.tgz#00c2f238019f24f6c0a194a26d41a1530ffe7bc4" + dependencies: + d3-dispatch "1" + d3-drag "1" + d3-interpolate "1" + d3-selection "1" + d3-transition "1" + +d3-chord@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.4.tgz#7dec4f0ba886f713fe111c45f763414f6f74ca2c" + dependencies: + d3-array "1" + d3-path "1" + +d3-collection@1, d3-collection@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.4.tgz#342dfd12837c90974f33f1cc0a785aea570dcdc2" + +d3-color@1, d3-color@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.0.3.tgz#bc7643fca8e53a8347e2fbdaffa236796b58509b" + +d3-dispatch@1, d3-dispatch@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.3.tgz#46e1491eaa9b58c358fce5be4e8bed626e7871f8" + +d3-drag@1, d3-drag@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.1.1.tgz#b5155304433b18ba38726b2184d0098e820dc64b" + dependencies: + d3-dispatch "1" + d3-selection "1" + +d3-dsv@1, d3-dsv@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.5.tgz#419f7db47f628789fc3fdb636e678449d0821136" + dependencies: + commander "2" + iconv-lite "0.4" + rw "1" + +d3-ease@1, d3-ease@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.3.tgz#68bfbc349338a380c44d8acc4fbc3304aa2d8c0e" + +d3-force@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.0.6.tgz#ea7e1b7730e2664cd314f594d6718c57cc132b79" + dependencies: + d3-collection "1" + d3-dispatch "1" + d3-quadtree "1" + d3-timer "1" + +d3-format@1, d3-format@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.2.0.tgz#6b480baa886885d4651dc248a8f4ac9da16db07a" + +d3-geo@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.6.4.tgz#f20e1e461cb1845f5a8be55ab6f876542a7e3199" + dependencies: + d3-array "1" + +d3-hierarchy@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz#a1c845c42f84a206bcf1c01c01098ea4ddaa7a26" + +d3-interpolate@1, d3-interpolate@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.5.tgz#69e099ff39214716e563c9aec3ea9d1ea4b8a79f" + dependencies: + d3-color "1" + +d3-path@1, d3-path@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.5.tgz#241eb1849bd9e9e8021c0d0a799f8a0e8e441764" + +d3-polygon@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.3.tgz#16888e9026460933f2b179652ad378224d382c62" + +d3-quadtree@1, d3-quadtree@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.3.tgz#ac7987e3e23fe805a990f28e1b50d38fcb822438" + +d3-queue@3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/d3-queue/-/d3-queue-3.0.7.tgz#c93a2e54b417c0959129d7d73f6cf7d4292e7618" + +d3-random@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.0.tgz#6642e506c6fa3a648595d2b2469788a8d12529d3" + +d3-request@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-request/-/d3-request-1.0.5.tgz#4daae946d1dd0d57dfe01f022956354958d51f23" + dependencies: + d3-collection "1" + d3-dispatch "1" + d3-dsv "1" + xmlhttprequest "1" + +d3-scale@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.6.tgz#bce19da80d3a0cf422c9543ae3322086220b34ed" + dependencies: + d3-array "^1.2.0" + d3-collection "1" + d3-color "1" + d3-format "1" + d3-interpolate "1" + d3-time "1" + d3-time-format "2" + +d3-selection@1, d3-selection@1.1.0, d3-selection@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.1.0.tgz#1998684896488f839ca0372123da34f1d318809c" + +d3-shape@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.2.0.tgz#45d01538f064bafd05ea3d6d2cb748fd8c41f777" + dependencies: + d3-path "1" + +d3-time-format@2, d3-time-format@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.0.5.tgz#9d7780204f7c9119c9170b1a56db4de9a8af972e" + dependencies: + d3-time "1" + +d3-time@1, d3-time@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.7.tgz#94caf6edbb7879bb809d0d1f7572bc48482f7270" + +d3-timer@1, d3-timer@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.6.tgz#4044bf15d7025c06ce7d1149f73cd07b54dbd784" + +d3-transition@1, d3-transition@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.1.0.tgz#cfc85c74e5239324290546623572990560c3966f" + dependencies: + d3-color "1" + d3-dispatch "1" + d3-ease "1" + d3-interpolate "1" + d3-selection "^1.1.0" + d3-timer "1" + +d3-voronoi@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c" + +d3-zoom@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.5.0.tgz#8417de9a077f98f9ce83b1998efb8ee12b4db26e" + dependencies: + d3-dispatch "1" + d3-drag "1" + d3-interpolate "1" + d3-selection "1" + d3-transition "1" + +d3@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-4.10.0.tgz#0bcca3a3b614e2fd45b1b5bd0b9164d57352a862" + dependencies: + d3-array "1.2.0" + d3-axis "1.0.8" + d3-brush "1.0.4" + d3-chord "1.0.4" + d3-collection "1.0.4" + d3-color "1.0.3" + d3-dispatch "1.0.3" + d3-drag "1.1.1" + d3-dsv "1.0.5" + d3-ease "1.0.3" + d3-force "1.0.6" + d3-format "1.2.0" + d3-geo "1.6.4" + d3-hierarchy "1.1.5" + d3-interpolate "1.1.5" + d3-path "1.0.5" + d3-polygon "1.0.3" + d3-quadtree "1.0.3" + d3-queue "3.0.7" + d3-random "1.1.0" + d3-request "1.0.5" + d3-scale "1.0.6" + d3-selection "1.1.0" + d3-shape "1.2.0" + d3-time "1.0.7" + d3-time-format "2.0.5" + d3-timer "1.0.6" + d3-transition "1.1.0" + d3-voronoi "1.1.2" + d3-zoom "1.5.0" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -2212,14 +2606,14 @@ https-proxy-agent@^1.0.0: debug "2" extend "3" +iconv-lite@0.4, iconv-lite@^0.4.17: + version "0.4.17" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" + iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" -iconv-lite@^0.4.17: - version "0.4.17" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" - icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" @@ -4177,6 +4571,10 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" @@ -5276,6 +5674,10 @@ xmlhttprequest-ssl@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" +xmlhttprequest@1: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"