diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts index 1a4854327a040..de027bfec5075 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/active-alert-list/active-alert-list.component.ts @@ -3,6 +3,7 @@ import { Component, Inject, OnInit, TemplateRef, ViewChild } from '@angular/core import { PrometheusService } from '~/app/shared/api/prometheus.service'; import { CellTemplate } from '~/app/shared/enum/cell-template.enum'; import { Icons } from '~/app/shared/enum/icons.enum'; +import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helper'; import { CdTableAction } from '~/app/shared/models/cd-table-action'; import { CdTableColumn } from '~/app/shared/models/cd-table-column'; import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; @@ -10,7 +11,6 @@ import { Permission } from '~/app/shared/models/permissions'; import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service'; import { URLBuilderService } from '~/app/shared/services/url-builder.service'; -import { PrometheusListHelper } from '../prometheus-list-helper'; const BASE_URL = 'silences'; // as only silence actions can be used diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts index e033729da3f3d..bdca7a1b70242 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/rules-list/rules-list.component.ts @@ -4,12 +4,12 @@ import _ from 'lodash'; import { PrometheusService } from '~/app/shared/api/prometheus.service'; import { CellTemplate } from '~/app/shared/enum/cell-template.enum'; +import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helper'; import { CdTableColumn } from '~/app/shared/models/cd-table-column'; import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; import { PrometheusRule } from '~/app/shared/models/prometheus-alerts'; import { DurationPipe } from '~/app/shared/pipes/duration.pipe'; import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service'; -import { PrometheusListHelper } from '../prometheus-list-helper'; @Component({ selector: 'cd-rules-list', diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts index 29af2bd2ae891..d5612a0949c05 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts @@ -4,7 +4,7 @@ import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { SortDirection, SortPropDir } from '@swimlane/ngx-datatable'; import { Observable, Subscriber } from 'rxjs'; -import { PrometheusListHelper } from '~/app/ceph/cluster/prometheus/prometheus-list-helper'; +import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helper'; import { SilenceFormComponent } from '~/app/ceph/cluster/prometheus/silence-form/silence-form.component'; import { PrometheusService } from '~/app/shared/api/prometheus.service'; import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.html index 1c1db13bc56ce..bab03a1704c2c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.html @@ -27,7 +27,7 @@ i18n>Cluster
+ *ngIf="isAlertmanagerConfigured && (prometheusAlertService.activeCriticalAlerts || prometheusAlertService.activeWarningAlerts)">
Alerts @@ -38,9 +38,9 @@ (click)="toggleAlertsWindow('danger')" id="dangerAlerts" i18n-title - *ngIf="crticialActiveAlerts"> + *ngIf="prometheusAlertService?.activeCriticalAlerts > 0"> - {{ crticialActiveAlerts }} + {{ prometheusAlertService.activeCriticalAlerts }}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.spec.ts index 68ee9b5486c19..fa24090976e12 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.spec.ts @@ -15,6 +15,7 @@ import { PrometheusService } from '~/app/shared/api/prometheus.service'; import { CssHelper } from '~/app/shared/classes/css-helper'; import { AlertmanagerAlert } from '~/app/shared/models/prometheus-alerts'; import { FeatureTogglesService } from '~/app/shared/services/feature-toggles.service'; +import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service'; import { SummaryService } from '~/app/shared/services/summary.service'; import { SharedModule } from '~/app/shared/shared.module'; import { configureTestBed } from '~/testing/unit-test-helper'; @@ -161,6 +162,13 @@ describe('Dashbord Component', () => { schemas: [NO_ERRORS_SCHEMA], providers: [ { provide: SummaryService, useClass: SummaryServiceMock }, + { + provide: PrometheusAlertService, + useValue: { + activeCriticalAlerts: 2, + activeWarningAlerts: 1 + } + }, CssHelper, PgCategoryService ] @@ -244,12 +252,12 @@ describe('Dashbord Component', () => { it('should show the actual alert count on each alerts pill', () => { fixture.detectChanges(); - const successNotification = fixture.debugElement.query(By.css('button[id=warningAlerts] span')); + const warningAlerts = fixture.debugElement.query(By.css('button[id=warningAlerts] span')); - const dangerNotification = fixture.debugElement.query(By.css('button[id=dangerAlerts] span')); + const dangerAlerts = fixture.debugElement.query(By.css('button[id=dangerAlerts] span')); - expect(successNotification.nativeElement.textContent).toBe('1'); - expect(dangerNotification.nativeElement.textContent).toBe('2'); + expect(warningAlerts.nativeElement.textContent).toBe('1'); + expect(dangerAlerts.nativeElement.textContent).toBe('2'); }); it('should show the critical alerts window and its content', () => { @@ -275,15 +283,16 @@ describe('Dashbord Component', () => { }); it('should only show the pills when the alerts are not empty', () => { - getAlertsSpy.and.returnValue(of({})); + spyOn(TestBed.inject(PrometheusAlertService), 'activeCriticalAlerts').and.returnValue(0); + spyOn(TestBed.inject(PrometheusAlertService), 'activeWarningAlerts').and.returnValue(0); fixture.detectChanges(); - const successNotification = fixture.debugElement.query(By.css('button[id=warningAlerts]')); + const warningAlerts = fixture.debugElement.query(By.css('button[id=warningAlerts]')); - const dangerNotification = fixture.debugElement.query(By.css('button[id=dangerAlerts]')); + const dangerAlerts = fixture.debugElement.query(By.css('button[id=dangerAlerts]')); - expect(successNotification).toBe(null); - expect(dangerNotification).toBe(null); + expect(warningAlerts).toBe(null); + expect(dangerAlerts).toBe(null); }); describe('features disabled', () => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.ts index e19cac146358e..8615444665a13 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/new-dashboard/dashboard/dashboard.component.ts @@ -23,13 +23,15 @@ import { } from '~/app/shared/services/feature-toggles.service'; import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.service'; import { SummaryService } from '~/app/shared/services/summary.service'; +import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helper'; +import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service'; @Component({ selector: 'cd-dashboard', templateUrl: './dashboard.component.html', styleUrls: ['./dashboard.component.scss'] }) -export class DashboardComponent implements OnInit, OnDestroy { +export class DashboardComponent extends PrometheusListHelper implements OnInit, OnDestroy { detailsCardData: DashboardDetails = {}; osdSettingsService: any; osdSettings: any; @@ -42,7 +44,6 @@ export class DashboardComponent implements OnInit, OnDestroy { healthData$: Observable; prometheusAlerts$: Observable; - isAlertmanagerConfigured = false; icons = Icons; showAlerts = false; flexHeight = true; @@ -53,8 +54,6 @@ export class DashboardComponent implements OnInit, OnDestroy { borderClass: string; alertType: string; alerts: AlertmanagerAlert[]; - crticialActiveAlerts: number; - warningActiveAlerts: number; healthData: any; categoryPgAmount: Record = {}; totalPgs = 0; @@ -86,16 +85,18 @@ export class DashboardComponent implements OnInit, OnDestroy { private featureToggles: FeatureTogglesService, private healthService: HealthService, public prometheusService: PrometheusService, - private refreshIntervalService: RefreshIntervalService + private refreshIntervalService: RefreshIntervalService, + public prometheusAlertService: PrometheusAlertService ) { + super(prometheusService); this.permissions = this.authStorageService.getPermissions(); this.enabledFeature$ = this.featureToggles.get(); } ngOnInit() { + super.ngOnInit(); this.interval = this.refreshIntervalService.intervalData$.subscribe(() => { this.getHealth(); - this.triggerPrometheusAlerts(); this.getCapacityCardData(); }); this.getPrometheusData(this.lastHourDateObject); @@ -113,6 +114,7 @@ export class DashboardComponent implements OnInit, OnDestroy { } toggleAlertsWindow(type: string, isToggleButton: boolean = false) { + this.triggerPrometheusAlerts(); if (isToggleButton) { this.showAlerts = !this.showAlerts; this.flexHeight = !this.flexHeight; @@ -159,56 +161,48 @@ export class DashboardComponent implements OnInit, OnDestroy { triggerPrometheusAlerts() { this.prometheusService.ifAlertmanagerConfigured(() => { - this.isAlertmanagerConfigured = true; - this.prometheusService.getAlerts().subscribe((alerts) => { this.alerts = alerts; - this.crticialActiveAlerts = alerts.filter( - (alert: AlertmanagerAlert) => - alert.status.state === 'active' && alert.labels.severity === 'critical' - ).length; - this.warningActiveAlerts = alerts.filter( - (alert: AlertmanagerAlert) => - alert.status.state === 'active' && alert.labels.severity === 'warning' - ).length; }); }); } getPrometheusData(selectedTime: any) { - if (this.timerGetPrometheusDataSub) { - this.timerGetPrometheusDataSub.unsubscribe(); - } - this.timerGetPrometheusDataSub = timer(0, this.timerTime).subscribe(() => { - selectedTime = this.updateTimeStamp(selectedTime); - - for (const queryName in queries) { - if (queries.hasOwnProperty(queryName)) { - const query = queries[queryName]; - let interval = selectedTime.step; - - if (query.includes('rate') && selectedTime.step < 20) { - interval = 20; - } else if (query.includes('rate')) { - interval = selectedTime.step * 2; + this.prometheusService.ifPrometheusConfigured(() => { + if (this.timerGetPrometheusDataSub) { + this.timerGetPrometheusDataSub.unsubscribe(); + } + this.timerGetPrometheusDataSub = timer(0, this.timerTime).subscribe(() => { + selectedTime = this.updateTimeStamp(selectedTime); + + for (const queryName in queries) { + if (queries.hasOwnProperty(queryName)) { + const query = queries[queryName]; + let interval = selectedTime.step; + + if (query.includes('rate') && selectedTime.step < 20) { + interval = 20; + } else if (query.includes('rate')) { + interval = selectedTime.step * 2; + } + + const intervalAdjustedQuery = query.replace(/\[(.*?)\]/g, `[${interval}s]`); + + this.prometheusService + .getPrometheusData({ + params: intervalAdjustedQuery, + start: selectedTime['start'], + end: selectedTime['end'], + step: selectedTime['step'] + }) + .subscribe((data: any) => { + if (data.result.length) { + this.queriesResults[queryName] = data.result[0].values; + } + }); } - - const intervalAdjustedQuery = query.replace(/\[(.*?)\]/g, `[${interval}s]`); - - this.prometheusService - .getPrometheusData({ - params: intervalAdjustedQuery, - start: selectedTime['start'], - end: selectedTime['end'], - step: selectedTime['step'] - }) - .subscribe((data: any) => { - if (data.result.length) { - this.queriesResults[queryName] = data.result[0].values; - } - }); } - } + }); }); } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/helpers/helpers.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/helpers/helpers.module.ts new file mode 100644 index 0000000000000..7f9b7d21efdcf --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/helpers/helpers.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +@NgModule({ + declarations: [], + imports: [CommonModule] +}) +export class HelpersModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-list-helper.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/helpers/prometheus-list-helper.ts similarity index 100% rename from src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/prometheus-list-helper.ts rename to src/pybind/mgr/dashboard/frontend/src/app/shared/helpers/prometheus-list-helper.ts