mirror of
https://github.com/ceph/ceph
synced 2026-08-02 07:03:18 +00:00
Merge pull request #65459 from rhcs-dashboard/72944-hide-suppresed-alerts-on-dashboard
mgr/dashboard : Hide suppressed alert on landing page Reviewed-by: Afreen Misbah <afreen@ibm.com> Reviewed-by: Nizamudeen A <nia@redhat.com>
This commit is contained in:
commit
7d5298b71a
@ -11,6 +11,7 @@
|
||||
<cd-table
|
||||
[data]="prometheusAlertService.alerts"
|
||||
[columns]="columns"
|
||||
[extraFilterableColumns]="filters"
|
||||
identifier="fingerprint"
|
||||
[forceIdentifier]="true"
|
||||
[customCss]="customCss"
|
||||
|
||||
@ -8,6 +8,7 @@ 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';
|
||||
import { Permission } from '~/app/shared/models/permissions';
|
||||
import { AlertState } from '~/app/shared/models/prometheus-alerts';
|
||||
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';
|
||||
@ -32,6 +33,21 @@ export class ActiveAlertListComponent extends PrometheusListHelper implements On
|
||||
expandedInnerRow: any;
|
||||
multilineTextKeys = ['description', 'impact', 'fix'];
|
||||
|
||||
filters: CdTableColumn[] = [
|
||||
{
|
||||
name: $localize`State`,
|
||||
prop: 'status.state',
|
||||
filterOptions: [$localize`All`, $localize`Active`, $localize`Suppressed`],
|
||||
filterInitValue: $localize`Active`,
|
||||
filterPredicate: (row, value) => {
|
||||
if (value === 'Active') return row.status?.state === AlertState.ACTIVE;
|
||||
else if (value === 'Suppressed') return row.status?.state === AlertState.SUPPRESSED;
|
||||
if (value === 'All') return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
// NotificationsComponent will refresh all alerts every 5s (No need to do it here as well)
|
||||
private authStorageService: AuthStorageService,
|
||||
|
||||
@ -102,7 +102,7 @@ describe('SilenceFormComponent', () => {
|
||||
|
||||
prometheus = new PrometheusHelper();
|
||||
prometheusService = TestBed.inject(PrometheusService);
|
||||
spyOn(prometheusService, 'getGroupedAlerts').and.callFake(() => {
|
||||
spyOn(prometheusService, 'getAlerts').and.callFake(() => {
|
||||
const name = _.split(router.url, '/').pop();
|
||||
return of([prometheus.createAlert(name)]);
|
||||
});
|
||||
@ -285,7 +285,7 @@ describe('SilenceFormComponent', () => {
|
||||
params = { id: 'alert0' };
|
||||
expectMode('alertAdd', false, false, 'Create');
|
||||
expect(prometheusService.getSilences).not.toHaveBeenCalled();
|
||||
expect(prometheusService.getGroupedAlerts).toHaveBeenCalled();
|
||||
expect(prometheusService.getAlerts).toHaveBeenCalled();
|
||||
expect(component.matchers).toEqual([createMatcher('alertname', 'alert0', false)]);
|
||||
expect(component.matcherMatch).toEqual({
|
||||
cssClass: 'has-success',
|
||||
|
||||
@ -19,7 +19,7 @@ import {
|
||||
AlertmanagerSilenceMatcherMatch
|
||||
} from '~/app/shared/models/alertmanager-silence';
|
||||
import { Permission } from '~/app/shared/models/permissions';
|
||||
import { GroupAlertmanagerAlert, PrometheusRule } from '~/app/shared/models/prometheus-alerts';
|
||||
import { AlertmanagerAlert, PrometheusRule } from '~/app/shared/models/prometheus-alerts';
|
||||
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
|
||||
import { ModalService } from '~/app/shared/services/modal.service';
|
||||
import { NotificationService } from '~/app/shared/services/notification.service';
|
||||
@ -225,7 +225,7 @@ export class SilenceFormComponent {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.prometheusService.getGroupedAlerts().subscribe((alerts) => {
|
||||
this.prometheusService.getAlerts().subscribe((alerts) => {
|
||||
const alert = _.find(alerts, ['fingerprint', params.id]);
|
||||
if (!_.isUndefined(alert)) {
|
||||
this.fillFormByAlert(alert);
|
||||
@ -258,7 +258,7 @@ export class SilenceFormComponent {
|
||||
this.form.updateValueAndValidity();
|
||||
}
|
||||
|
||||
private fillFormByAlert(alert: GroupAlertmanagerAlert) {
|
||||
private fillFormByAlert(alert: AlertmanagerAlert) {
|
||||
const labels = alert.labels;
|
||||
this.setMatcher({
|
||||
name: 'alertname',
|
||||
|
||||
@ -288,8 +288,8 @@
|
||||
<ng-container *ngFor="let alert of prometheusAlertService.alerts; let i = index; trackBy: trackByFn">
|
||||
<div [ngClass]="['border-'+alertClass[alert.labels.severity]]"
|
||||
*ngIf="alert.status.state === 'active' &&
|
||||
alert.labels.severity === alertType ||
|
||||
!alertType">
|
||||
(alert.labels.severity === alertType ||
|
||||
!alertType)">
|
||||
<div class="card tc_alerts border-0 pt-3">
|
||||
<div class="row no-gutters ps-2">
|
||||
<div class="col-sm-1 text-center">
|
||||
@ -309,6 +309,7 @@
|
||||
[title]="alert.startsAt | cdDate"
|
||||
i18n>Active since: {{ alert.startsAt | relativeDate }}</small>
|
||||
<small class="alert_count"
|
||||
*ngIf="alert.alert_count > 1"
|
||||
[title]="alert.alert_count"
|
||||
i18n>Total occurrences: {{ alert.alert_count }}</small>
|
||||
</p>
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
type AlertState = 'active' | 'suppressed' | 'resolved' | 'unprocessed';
|
||||
|
||||
export class PrometheusAlertLabels {
|
||||
alertname: string;
|
||||
instance: string;
|
||||
@ -48,7 +50,7 @@ export class PrometheusRule {
|
||||
|
||||
export class AlertmanagerAlert extends CommonAlertmanagerAlert {
|
||||
status: {
|
||||
state: 'unprocessed' | 'active' | 'suppressed';
|
||||
state: AlertState;
|
||||
silencedBy: null | string[];
|
||||
inhibitedBy: null | string[];
|
||||
};
|
||||
@ -84,10 +86,17 @@ export class AlertmanagerNotification {
|
||||
}
|
||||
|
||||
export class PrometheusCustomAlert {
|
||||
status: 'resolved' | 'unprocessed' | 'active' | 'suppressed';
|
||||
status: AlertState;
|
||||
name: string;
|
||||
url: string;
|
||||
description: string;
|
||||
fingerprint?: string | boolean;
|
||||
severity?: string;
|
||||
}
|
||||
|
||||
export const AlertState = {
|
||||
ACTIVE: 'active' as AlertState,
|
||||
SUPPRESSED: 'suppressed' as AlertState,
|
||||
RESOLVED: 'resolved' as AlertState,
|
||||
UNPROCCESSED: 'unprocessed' as AlertState
|
||||
};
|
||||
|
||||
@ -7,7 +7,8 @@ import {
|
||||
AlertmanagerAlert,
|
||||
PrometheusCustomAlert,
|
||||
PrometheusRule,
|
||||
GroupAlertmanagerAlert
|
||||
GroupAlertmanagerAlert,
|
||||
AlertState
|
||||
} from '../models/prometheus-alerts';
|
||||
import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
@ -64,10 +65,15 @@ export class PrometheusAlertService {
|
||||
|
||||
private handleAlerts(alertGroups: GroupAlertmanagerAlert[]) {
|
||||
const alerts: AlertmanagerAlert[] = alertGroups
|
||||
.map((g) => {
|
||||
if (!g.alerts.length) return null;
|
||||
if (g.alerts.length === 1) return { ...g.alerts[0], alert_count: 1 };
|
||||
return { ...g.alerts[0], alert_count: g.alerts.length, subalerts: g.alerts };
|
||||
.map((group) => {
|
||||
if (!group.alerts.length) return null;
|
||||
if (group.alerts.length === 1) return { ...group.alerts[0], alert_count: 1 };
|
||||
const hasActive = group.alerts.some(
|
||||
(alert: AlertmanagerAlert) => alert.status.state === AlertState.ACTIVE
|
||||
);
|
||||
const parent = { ...group.alerts[0] };
|
||||
if (hasActive) parent.status.state = AlertState.ACTIVE;
|
||||
return { ...parent, alert_count: group.alerts.length, subalerts: group.alerts };
|
||||
})
|
||||
.filter(Boolean) as AlertmanagerAlert[];
|
||||
|
||||
@ -78,19 +84,23 @@ export class PrometheusAlertService {
|
||||
}
|
||||
this.activeAlerts = _.reduce<AlertmanagerAlert, number>(
|
||||
alerts,
|
||||
(result, alert) => (alert.status.state === 'active' ? ++result : result),
|
||||
(result, alert) => (alert.status.state === AlertState.ACTIVE ? ++result : result),
|
||||
0
|
||||
);
|
||||
this.activeCriticalAlerts = _.reduce<AlertmanagerAlert, number>(
|
||||
alerts,
|
||||
(result, alert) =>
|
||||
alert.status.state === 'active' && alert.labels.severity === 'critical' ? ++result : result,
|
||||
alert.status.state === AlertState.ACTIVE && alert.labels.severity === 'critical'
|
||||
? ++result
|
||||
: result,
|
||||
0
|
||||
);
|
||||
this.activeWarningAlerts = _.reduce<AlertmanagerAlert, number>(
|
||||
alerts,
|
||||
(result, alert) =>
|
||||
alert.status.state === 'active' && alert.labels.severity === 'warning' ? ++result : result,
|
||||
alert.status.state === AlertState.ACTIVE && alert.labels.severity === 'warning'
|
||||
? ++result
|
||||
: result,
|
||||
0
|
||||
);
|
||||
this.alerts = alerts
|
||||
@ -105,7 +115,7 @@ export class PrometheusAlertService {
|
||||
this.alertFormatter.convertToCustomAlerts(oldAlerts)
|
||||
);
|
||||
const suppressedFiltered = _.filter(changedAlerts, (alert) => {
|
||||
return alert.status !== 'suppressed';
|
||||
return alert.status !== AlertState.SUPPRESSED;
|
||||
});
|
||||
const notifications = suppressedFiltered.map((alert) =>
|
||||
this.alertFormatter.convertAlertToNotification(alert)
|
||||
@ -121,7 +131,7 @@ export class PrometheusAlertService {
|
||||
private getVanishedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
|
||||
return _.differenceWith(oldAlerts, alerts, (a, b) => a.fingerprint === b.fingerprint).map(
|
||||
(alert) => {
|
||||
alert.status = 'resolved';
|
||||
alert.status = AlertState.RESOLVED;
|
||||
return alert;
|
||||
}
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user