From 880f77101dc645cc059626e9ed6d8abccdf8a3c8 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Tue, 5 Nov 2019 17:42:40 +0000 Subject: [PATCH] Update metric used for cells - `firehose_value_metric_rep_unhealthy_cell` deprecated, now use `firehose_value_metric_rep_garden_health_check_failed` - Try new metric first and fall back on old --- .../core/src/core/endpoints.service.ts | 55 ++------------- .../features/cloud-foundry/cf-cell.helpers.ts | 68 +++++++++++++++++++ .../cloud-foundry-cell.service.ts | 54 +++++++++++---- .../cloud-foundry-cells.component.ts | 14 +++- .../features/endpoints/endpoint-helpers.ts | 12 +++- .../cf-app-instances-config.service.ts | 10 +-- .../list-types/base-cf/base-cf-list-config.ts | 3 + .../cf-cell-health-list-config.service.ts | 40 ++++++----- .../cf-cells/cf-cells-data-source.ts | 24 +++---- .../cf-cells/cf-cells-list-config.service.ts | 36 +++++++--- .../plugins/metrics/cloud_foundry.go | 2 +- 11 files changed, 202 insertions(+), 116 deletions(-) create mode 100644 src/frontend/packages/core/src/features/cloud-foundry/cf-cell.helpers.ts diff --git a/src/frontend/packages/core/src/core/endpoints.service.ts b/src/frontend/packages/core/src/core/endpoints.service.ts index 24a209c705..72f6507beb 100644 --- a/src/frontend/packages/core/src/core/endpoints.service.ts +++ b/src/frontend/packages/core/src/core/endpoints.service.ts @@ -1,26 +1,16 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router'; import { Store } from '@ngrx/store'; -import { combineLatest as observableCombineLatest, Observable, of } from 'rxjs'; -import { filter, first, map, skipWhile, switchMap, withLatestFrom } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { first, map, skipWhile, withLatestFrom } from 'rxjs/operators'; -import { FetchCFCellMetricsPaginatedAction, MetricQueryConfig } from '../../../store/src/actions/metrics.actions'; import { RouterNav } from '../../../store/src/actions/router.actions'; import { AppState, IRequestEntityTypeState } from '../../../store/src/app-state'; -import { entityFactory } from '../../../store/src/helpers/entity-factory'; import { AuthState } from '../../../store/src/reducers/auth.reducer'; -import { getPaginationObservables } from '../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; -import { - endpointEntitiesSelector, - endpointsEntityRequestDataSelector, - endpointStatusSelector, -} from '../../../store/src/selectors/endpoint.selectors'; -import { IMetrics } from '../../../store/src/types/base-metric.types'; +import { endpointEntitiesSelector, endpointStatusSelector } from '../../../store/src/selectors/endpoint.selectors'; import { EndpointModel, EndpointState } from '../../../store/src/types/endpoint.types'; import { EndpointHealthCheck, endpointHealthChecks } from '../../endpoints-health-checks'; -import { getEndpointType } from '../features/endpoints/endpoint-helpers'; -import { PaginationMonitorFactory } from '../shared/monitors/pagination-monitor.factory'; -import { MetricQueryType } from '../shared/services/metrics-range-selector.types'; +import { endpointHasMetricsByAvailable, getEndpointType } from '../features/endpoints/endpoint-helpers'; import { UserService } from './user.service'; @@ -47,7 +37,6 @@ export class EndpointsService implements CanActivate { constructor( private store: Store, private userService: UserService, - private paginationMonitorFactory: PaginationMonitorFactory ) { this.endpoints$ = store.select(endpointEntitiesSelector); this.haveRegistered$ = this.endpoints$.pipe(map(endpoints => !!Object.keys(endpoints).length)); @@ -122,41 +111,7 @@ export class EndpointsService implements CanActivate { } hasMetrics(endpointId: string): Observable { - return this.store.select(endpointsEntityRequestDataSelector(endpointId)).pipe( - filter(endpoint => !!endpoint), - map(endpoint => endpoint.metricsAvailable), - first() - ); - } - - hasCellMetrics(endpointId: string): Observable { - return this.hasMetrics(endpointId).pipe( - switchMap(hasMetrics => { - if (!hasMetrics) { - return of(false); - } - - // Check that we successfully retrieve some stats. If the metric is unknown an empty list is returned - const action = new FetchCFCellMetricsPaginatedAction( - endpointId, - endpointId, - new MetricQueryConfig('firehose_value_metric_rep_unhealthy_cell', {}), - MetricQueryType.QUERY - ); - return getPaginationObservables({ - store: this.store, - action, - paginationMonitor: this.paginationMonitorFactory.create( - action.paginationKey, - entityFactory(action.entityKey) - ) - }).entities$.pipe( - filter(entities => !!entities && !!entities.length), - map(entities => !!entities.find(entity => !!entity.data.result.length)), - first() - ); - }) - ); + return endpointHasMetricsByAvailable(this.store, endpointId); } doesNotHaveConnectedEndpointType(type: string): Observable { diff --git a/src/frontend/packages/core/src/features/cloud-foundry/cf-cell.helpers.ts b/src/frontend/packages/core/src/features/cloud-foundry/cf-cell.helpers.ts new file mode 100644 index 0000000000..0eb64a6e72 --- /dev/null +++ b/src/frontend/packages/core/src/features/cloud-foundry/cf-cell.helpers.ts @@ -0,0 +1,68 @@ +import { Store } from '@ngrx/store'; +import { Observable, of } from 'rxjs'; +import { filter, first, map, publishReplay, refCount, switchMap } from 'rxjs/operators'; + +import { FetchCFCellMetricsPaginatedAction, MetricQueryConfig } from '../../../../store/src/actions/metrics.actions'; +import { AppState } from '../../../../store/src/app-state'; +import { entityFactory } from '../../../../store/src/helpers/entity-factory'; +import { getPaginationObservables } from '../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; +import { IMetrics } from '../../../../store/src/types/base-metric.types'; +import { PaginationMonitorFactory } from '../../shared/monitors/pagination-monitor.factory'; +import { MetricQueryType } from '../../shared/services/metrics-range-selector.types'; +import { endpointHasMetricsByAvailable } from '../endpoints/endpoint-helpers'; +import { CellMetrics } from './tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service'; + +export class CfCellHelper { + + constructor( + private store: Store, + private paginationMonitorFactory: PaginationMonitorFactory) { + } + + public createCellMetricAction(cfId: string, cellId?: string): Observable { + const cellIdString = !!cellId ? `{bosh_job_id="${cellId}"}` : ''; + + const newMetricAction: FetchCFCellMetricsPaginatedAction = new FetchCFCellMetricsPaginatedAction( + cfId, + cfId, + new MetricQueryConfig(CellMetrics.HEALTHY + cellIdString, {}), + MetricQueryType.QUERY + ); + return this.hasMetric(newMetricAction).pipe( + switchMap(hasNewMetric => hasNewMetric ? + of(hasNewMetric) : + this.hasMetric(new FetchCFCellMetricsPaginatedAction( + cfId, + cfId, + new MetricQueryConfig(CellMetrics.HEALTHY_DEP + cellIdString, {}), + MetricQueryType.QUERY + )) + ) + ); + } + + private hasMetric(action: FetchCFCellMetricsPaginatedAction): Observable { + return getPaginationObservables({ + store: this.store, + action, + paginationMonitor: this.paginationMonitorFactory.create( + action.paginationKey, + entityFactory(action.entityKey) + ) + }).entities$.pipe( + filter(entities => !!entities && !!entities.length), + first(), + map(entities => !!entities.find(entity => !!entity.data.result.length) ? action : null), + publishReplay(1), + refCount() + ); + } + + public hasCellMetrics(endpointId: string): Observable { + return endpointHasMetricsByAvailable(this.store, endpointId).pipe( + // If metrics set up for this endpoint check if we can fetch cell metrics from it. + // If the metric is unknown an empty list is returned + switchMap(hasMetrics => hasMetrics ? this.createCellMetricAction(endpointId).pipe(map(action => !!action)) : of(false)) + ); + } +} diff --git a/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts b/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts index 15349c90a6..b82ca62c62 100644 --- a/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts +++ b/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service.ts @@ -1,21 +1,32 @@ import { Injectable } from '@angular/core'; +import { Store } from '@ngrx/store'; import { combineLatest, Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { map, switchMap } from 'rxjs/operators'; +import { FetchCFCellMetricsAction, MetricQueryConfig } from '../../../../../../../store/src/actions/metrics.actions'; +import { AppState } from '../../../../../../../store/src/app-state'; +import { entityFactory, metricSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; +import { IMetricMatrixResult, IMetrics, IMetricVectorResult } from '../../../../../../../store/src/types/base-metric.types'; +import { IMetricCell } from '../../../../../../../store/src/types/metric.types'; import { EntityServiceFactory } from '../../../../../core/entity-service-factory.service'; import { MetricsConfig } from '../../../../../shared/components/metrics-chart/metrics-chart.component'; import { MetricsLineChartConfig } from '../../../../../shared/components/metrics-chart/metrics-chart.types'; import { MetricsChartHelpers } from '../../../../../shared/components/metrics-chart/metrics.component.helpers'; +import { PaginationMonitorFactory } from '../../../../../shared/monitors/pagination-monitor.factory'; import { MetricQueryType } from '../../../../../shared/services/metrics-range-selector.types'; +import { CfCellHelper } from '../../../cf-cell.helpers'; import { ActiveRouteCfCell } from '../../../cf-page.types'; -import { IMetricCell } from '../../../../../../../store/src/types/metric.types'; -import { IMetricMatrixResult, IMetrics, IMetricVectorResult } from '../../../../../../../store/src/types/base-metric.types'; -import { FetchCFCellMetricsAction, MetricQueryConfig } from '../../../../../../../store/src/actions/metrics.actions'; -import { metricSchemaKey, entityFactory } from '../../../../../../../store/src/helpers/entity-factory'; export const enum CellMetrics { - HEALTHY = 'firehose_value_metric_rep_unhealthy_cell', + /** + * Deprecated since Diego v2.31.0. See https://github.com/bosh-prometheus/prometheus-boshrelease/issues/333 + */ + HEALTHY_DEP = 'firehose_value_metric_rep_unhealthy_cell', + /** + * Available from Diego v2.31.0. See https://github.com/bosh-prometheus/prometheus-boshrelease/issues/333 + */ + HEALTHY = 'firehose_value_metric_rep_garden_health_check_failed', REMAINING_CONTAINERS = 'firehose_value_metric_rep_capacity_remaining_containers', REMAINING_DISK = 'firehose_value_metric_rep_capacity_remaining_disk', REMAINING_MEMORY = 'firehose_value_metric_rep_capacity_remaining_memory', @@ -25,6 +36,10 @@ export const enum CellMetrics { CPUS = 'firehose_value_metric_rep_num_cpus' } + +/** + * Designed to be used once drilled down to a cell (see ActiveRouteCfCell) + */ @Injectable() export class CloudFoundryCellService { @@ -50,12 +65,13 @@ export class CloudFoundryCellService { constructor( activeRouteCfCell: ActiveRouteCfCell, - private entityServiceFactory: EntityServiceFactory) { + private entityServiceFactory: EntityServiceFactory, + store: Store, + paginationMonitorFactory: PaginationMonitorFactory) { this.cellId = activeRouteCfCell.cellId; this.cfGuid = activeRouteCfCell.cfGuid; - this.healthy$ = this.generate(CellMetrics.HEALTHY); this.remainingContainers$ = this.generate(CellMetrics.REMAINING_CONTAINERS); this.totalContainers$ = this.generate(CellMetrics.TOTAL_CONTAINERS); this.remainingDisk$ = this.generate(CellMetrics.REMAINING_DISK); @@ -68,8 +84,19 @@ export class CloudFoundryCellService { this.usageDisk$ = this.generateUsage(this.remainingDisk$, this.totalDisk$); this.usageMemory$ = this.generateUsage(this.remainingMemory$, this.totalMemory$); - this.cellMetric$ = this.generate(CellMetrics.HEALTHY, true); - + const cellHelper = new CfCellHelper(store, paginationMonitorFactory); + const action$ = cellHelper.createCellMetricAction(this.cfGuid); + this.cellMetric$ = action$.pipe( + switchMap(action => { + this.healthyMetricId = action.guid; + return this.generate(action.query.metric as CellMetrics, true); + }) + ); + this.healthy$ = action$.pipe( + switchMap(action => { + return this.generate(action.query.metric as CellMetrics, false); + }) + ); } public buildMetricConfig( @@ -97,17 +124,14 @@ export class CloudFoundryCellService { return lineChartConfig; } - private generate(metric: CellMetrics, isMetric = false): Observable { - const action = new FetchCFCellMetricsAction( + private generate(metric: CellMetrics, isMetric = false, customAction?: FetchCFCellMetricsAction): Observable { + const action = customAction || new FetchCFCellMetricsAction( this.cfGuid, this.cellId, new MetricQueryConfig(metric + `{bosh_job_id="${this.cellId}"}`, {}), MetricQueryType.QUERY, false ); - if (metric === CellMetrics.HEALTHY) { - this.healthyMetricId = action.guid; - } return this.entityServiceFactory.create>>( metricSchemaKey, entityFactory(metricSchemaKey), diff --git a/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cells.component.ts b/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cells.component.ts index 30fa2d93f0..045b17406f 100644 --- a/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cells.component.ts +++ b/src/frontend/packages/core/src/features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cells.component.ts @@ -1,11 +1,14 @@ import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { EndpointsService } from '../../../../core/endpoints.service'; +import { AppState } from '../../../../../../store/src/app-state'; import { CfCellsListConfigService, } from '../../../../shared/components/list/list-types/cf-cells/cf-cells-list-config.service'; import { ListConfig } from '../../../../shared/components/list/list.component.types'; +import { PaginationMonitorFactory } from '../../../../shared/monitors/pagination-monitor.factory'; +import { CfCellHelper } from '../../cf-cell.helpers'; import { getActiveRouteCfCellProvider } from '../../cf.helpers'; import { CloudFoundryEndpointService } from '../../services/cloud-foundry-endpoint.service'; @@ -24,7 +27,12 @@ import { CloudFoundryEndpointService } from '../../services/cloud-foundry-endpoi export class CloudFoundryCellsComponent { hasCellMetrics$: Observable; - constructor(endpointService: EndpointsService, cfEndpointService: CloudFoundryEndpointService) { - this.hasCellMetrics$ = endpointService.hasCellMetrics(cfEndpointService.cfGuid); + constructor( + cfEndpointService: CloudFoundryEndpointService, + store: Store, + paginationMonitorFactory: PaginationMonitorFactory + ) { + const cellHelper = new CfCellHelper(store, paginationMonitorFactory); + this.hasCellMetrics$ = cellHelper.hasCellMetrics(cfEndpointService.cfGuid); } } diff --git a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts index 5b81d064cb..a35372f7da 100644 --- a/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts +++ b/src/frontend/packages/core/src/features/endpoints/endpoint-helpers.ts @@ -2,11 +2,12 @@ import { Type } from '@angular/core'; import { Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; -import { first, map } from 'rxjs/operators'; +import { filter, first, map } from 'rxjs/operators'; import { AppState } from '../../../../store/src/app-state'; import { endpointSchemaKey } from '../../../../store/src/helpers/entity-factory'; import { selectEntities } from '../../../../store/src/selectors/api.selectors'; +import { endpointsEntityRequestDataSelector } from '../../../../store/src/selectors/endpoint.selectors'; import { EndpointModel } from '../../../../store/src/types/endpoint.types'; import { ExtensionService } from '../../core/extension/extension-service'; import { @@ -195,6 +196,15 @@ export function endpointHasMetrics(endpointGuid: string, store: Store) ); } +// There are two different methods for checking if an endpoint has metrics. Need to understand use cases +export function endpointHasMetricsByAvailable(store: Store, endpointId: string): Observable { + return store.select(endpointsEntityRequestDataSelector(endpointId)).pipe( + filter(endpoint => !!endpoint), + map(endpoint => endpoint.metricsAvailable), + first() + ); +} + export function getEndpointAuthTypes() { return endpointAuthTypes; } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts index ba3a782089..5329c4e6e9 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/app-instance/cf-app-instances-config.service.ts @@ -10,10 +10,11 @@ import { AppState } from '../../../../../../../store/src/app-state'; import { entityFactory, metricSchemaKey } from '../../../../../../../store/src/helpers/entity-factory'; import { IMetricMatrixResult, IMetrics } from '../../../../../../../store/src/types/base-metric.types'; import { IMetricApplication } from '../../../../../../../store/src/types/metric.types'; -import { EndpointsService } from '../../../../../core/endpoints.service'; import { EntityServiceFactory } from '../../../../../core/entity-service-factory.service'; import { UtilsService } from '../../../../../core/utils.service'; import { ApplicationService } from '../../../../../features/applications/application.service'; +import { CfCellHelper } from '../../../../../features/cloud-foundry/cf-cell.helpers'; +import { PaginationMonitorFactory } from '../../../../monitors/pagination-monitor.factory'; import { MetricQueryType } from '../../../../services/metrics-range-selector.types'; import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../confirmation-dialog.service'; @@ -189,11 +190,12 @@ export class CfAppInstancesConfigService implements IListConfig private utilsService: UtilsService, private router: Router, private confirmDialog: ConfirmationDialogService, - private endpointsService: EndpointsService, - entityServiceFactory: EntityServiceFactory + entityServiceFactory: EntityServiceFactory, + paginationMonitorFactory: PaginationMonitorFactory ) { + const cellHelper = new CfCellHelper(store, paginationMonitorFactory); - this.initialised$ = this.endpointsService.hasCellMetrics(appService.cfGuid).pipe( + this.initialised$ = cellHelper.hasCellMetrics(appService.cfGuid).pipe( map(hasMetrics => { if (hasMetrics) { this.columns.splice(1, 0, this.cfCellColumn); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/base-cf/base-cf-list-config.ts b/src/frontend/packages/core/src/shared/components/list/list-types/base-cf/base-cf-list-config.ts index a2156d434d..f80d504f81 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/base-cf/base-cf-list-config.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/base-cf/base-cf-list-config.ts @@ -1,3 +1,5 @@ +import { of } from 'rxjs'; + import { ListView } from '../../../../../../../store/src/actions/list.actions'; import { IListDataSource } from '../../data-sources-controllers/list-data-source-types'; import { CardTypes } from '../../list-cards/card/card.component'; @@ -17,4 +19,5 @@ export class BaseCfListConfig implements IListConfig { getMultiActions = () => []; getSingleActions = () => []; getMultiFiltersConfigs = () => []; + getInitialised = () => of(true); } diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-cell-health/cf-cell-health-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-cell-health/cf-cell-health-list-config.service.ts index df3c6d6fe0..f276d1a641 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-cell-health/cf-cell-health-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-cell-health/cf-cell-health-list-config.service.ts @@ -1,17 +1,17 @@ import { DatePipe } from '@angular/common'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { first, tap } from 'rxjs/operators'; import { ListView } from '../../../../../../../store/src/actions/list.actions'; -import { - FetchCFCellMetricsPaginatedAction, - MetricQueryConfig, -} from '../../../../../../../store/src/actions/metrics.actions'; +import { FetchCFCellMetricsPaginatedAction } from '../../../../../../../store/src/actions/metrics.actions'; import { AppState } from '../../../../../../../store/src/app-state'; +import { CfCellHelper } from '../../../../../features/cloud-foundry/cf-cell.helpers'; import { CloudFoundryCellService, } from '../../../../../features/cloud-foundry/tabs/cloud-foundry-cells/cloud-foundry-cell/cloud-foundry-cell.service'; -import { MetricQueryType } from '../../../../services/metrics-range-selector.types'; +import { PaginationMonitorFactory } from '../../../../monitors/pagination-monitor.factory'; import { BooleanIndicatorType } from '../../../boolean-indicator/boolean-indicator.component'; import { TableCellBooleanIndicatorComponent, @@ -33,6 +33,7 @@ export class CfCellHealthListConfigService extends BaseCfListConfig; private boolIndicatorConfig: TableCellBooleanIndicatorComponentConfig = { isEnabled: (row: CfCellHealthEntry) => @@ -42,25 +43,28 @@ export class CfCellHealthListConfigService extends BaseCfListConfig, cloudFoundryCellService: CloudFoundryCellService, private datePipe: DatePipe) { + constructor( + private store: Store, + cloudFoundryCellService: CloudFoundryCellService, + private datePipe: DatePipe, + private paginationMonitorFactory: PaginationMonitorFactory) { super(); - const action = this.createMetricsAction(cloudFoundryCellService.cfGuid, cloudFoundryCellService.cellId); - this.dataSource = new CfCellHealthDataSource(store, this, action); + + this.init$ = this.createMetricsAction(cloudFoundryCellService.cfGuid, cloudFoundryCellService.cellId).pipe( + first(), + tap(action => { + this.dataSource = new CfCellHealthDataSource(store, this, action); + }) + ); this.showCustomTime = true; } - private createMetricsAction(cfGuid: string, cellId: string): FetchCFCellMetricsPaginatedAction { - const action = new FetchCFCellMetricsPaginatedAction( - cfGuid, - cellId, - new MetricQueryConfig(`firehose_value_metric_rep_unhealthy_cell{bosh_job_id="${cellId}"}`, {}), - MetricQueryType.QUERY - ); - action.initialParams['order-direction-field'] = 'dateTime'; - action.initialParams['order-direction'] = 'asc'; - return action; + private createMetricsAction(cfGuid: string, cellId: string): Observable { + const cellHelper = new CfCellHelper(this.store, this.paginationMonitorFactory); + return cellHelper.createCellMetricAction(cfGuid, cellId); } + getInitialised = () => this.init$; getColumns = (): ITableColumn[] => [ { columnId: 'dateTime', diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-data-source.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-data-source.ts index 4e17d73611..e1ee4d002d 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-data-source.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-data-source.ts @@ -1,14 +1,13 @@ import { Store } from '@ngrx/store'; import { map } from 'rxjs/operators'; -import { MetricQueryType } from '../../../../services/metrics-range-selector.types'; -import { ListDataSource } from '../../data-sources-controllers/list-data-source'; -import { IListConfig } from '../../list.component.types'; -import { IMetricVectorResult, IMetrics } from '../../../../../../../store/src/types/base-metric.types'; -import { IMetricCell } from '../../../../../../../store/src/types/metric.types'; +import { FetchCFCellMetricsPaginatedAction } from '../../../../../../../store/src/actions/metrics.actions'; import { AppState } from '../../../../../../../store/src/app-state'; -import { MetricQueryConfig, FetchCFCellMetricsPaginatedAction } from '../../../../../../../store/src/actions/metrics.actions'; import { entityFactory } from '../../../../../../../store/src/helpers/entity-factory'; +import { IMetrics, IMetricVectorResult } from '../../../../../../../store/src/types/base-metric.types'; +import { IMetricCell } from '../../../../../../../store/src/types/metric.types'; +import { ListDataSource } from '../../data-sources-controllers/list-data-source'; +import { IListConfig } from '../../list.component.types'; export class CfCellsDataSource extends ListDataSource, IMetrics>> { @@ -18,14 +17,11 @@ export class CfCellsDataSource static cellHealthyPath = 'value.1'; static cellDeploymentPath = 'metric.bosh_deployment'; - constructor(store: Store, cfGuid: string, listConfig: IListConfig>) { - const action = new FetchCFCellMetricsPaginatedAction( - cfGuid, - cfGuid, - new MetricQueryConfig('firehose_value_metric_rep_unhealthy_cell', {}), - MetricQueryType.QUERY - ); - + constructor( + store: Store, + listConfig: IListConfig>, + action: FetchCFCellMetricsPaginatedAction + ) { super({ store, action, diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-list-config.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-list-config.service.ts index ca98d13909..d6451a54cd 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-list-config.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/cf-cells/cf-cells-list-config.service.ts @@ -1,19 +1,24 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { BaseCfListConfig } from '../base-cf/base-cf-list-config'; +import { Observable } from 'rxjs'; +import { first, tap } from 'rxjs/operators'; + +import { ListView } from '../../../../../../../store/src/actions/list.actions'; +import { AppState } from '../../../../../../../store/src/app-state'; import { IMetricVectorResult } from '../../../../../../../store/src/types/base-metric.types'; import { IMetricCell } from '../../../../../../../store/src/types/metric.types'; -import { CfCellsDataSource } from './cf-cells-data-source'; -import { ListView } from '../../../../../../../store/src/actions/list.actions'; -import { ListViewTypes } from '../../list.component.types'; +import { CfCellHelper } from '../../../../../features/cloud-foundry/cf-cell.helpers'; +import { ActiveRouteCfCell } from '../../../../../features/cloud-foundry/cf-page.types'; +import { PaginationMonitorFactory } from '../../../../monitors/pagination-monitor.factory'; +import { BooleanIndicatorType } from '../../../boolean-indicator/boolean-indicator.component'; import { + TableCellBooleanIndicatorComponent, TableCellBooleanIndicatorComponentConfig, - TableCellBooleanIndicatorComponent } from '../../list-table/table-cell-boolean-indicator/table-cell-boolean-indicator.component'; -import { BooleanIndicatorType } from '../../../boolean-indicator/boolean-indicator.component'; import { ITableColumn } from '../../list-table/table.types'; -import { AppState } from '../../../../../../../store/src/app-state'; -import { ActiveRouteCfCell } from '../../../../../features/cloud-foundry/cf-page.types'; +import { ListViewTypes } from '../../list.component.types'; +import { BaseCfListConfig } from '../base-cf/base-cf-list-config'; +import { CfCellsDataSource } from './cf-cells-data-source'; @@ -29,6 +34,7 @@ export class CfCellsListConfigService extends BaseCfListConfig; private boolIndicatorConfig: TableCellBooleanIndicatorComponentConfig> = { // "0 signifies healthy, and 1 signifies unhealthy" @@ -94,11 +100,21 @@ export class CfCellsListConfigService extends BaseCfListConfig, private activeRouteCfCell: ActiveRouteCfCell) { + constructor( + store: Store, + private activeRouteCfCell: ActiveRouteCfCell, + paginationMonitorFactory: PaginationMonitorFactory) { super(); - this.dataSource = new CfCellsDataSource(store, activeRouteCfCell.cfGuid, this); + const cellHelper = new CfCellHelper(store, paginationMonitorFactory); + this.init$ = cellHelper.createCellMetricAction(activeRouteCfCell.cfGuid).pipe( + first(), + tap(action => { + this.dataSource = new CfCellsDataSource(store, this, action); + }) + ); } + getInitialised = () => this.init$; getColumns = () => this.columns; getDataSource = () => this.dataSource; } diff --git a/src/jetstream/plugins/metrics/cloud_foundry.go b/src/jetstream/plugins/metrics/cloud_foundry.go index f7fa8c8e84..7fd1e6e1e2 100644 --- a/src/jetstream/plugins/metrics/cloud_foundry.go +++ b/src/jetstream/plugins/metrics/cloud_foundry.go @@ -15,6 +15,7 @@ import ( var ( cellQueryWhiteList = []string{ "firehose_value_metric_rep_unhealthy_cell", + "firehose_value_metric_rep_garden_health_check_failed", "firehose_value_metric_rep_capacity_remaining_containers", "firehose_value_metric_rep_capacity_remaining_disk", "firehose_value_metric_rep_capacity_remaining_memory", @@ -205,6 +206,5 @@ func (m *MetricsSpecification) getCloudFoundryCellMetrics(c echo.Context) error } cnsiList := strings.Split(c.Request().Header.Get("x-cap-cnsi-list"), ",") - return m.makePrometheusRequest(c, cnsiList, "") }