]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / services / prometheus-alert.service.ts
CommitLineData
11fdf7f2
TL
1import { Injectable } from '@angular/core';
2
f67539c2 3import _ from 'lodash';
11fdf7f2
TL
4
5import { PrometheusService } from '../api/prometheus.service';
9f95a23c
TL
6import {
7 AlertmanagerAlert,
8 PrometheusCustomAlert,
9 PrometheusRule
10} from '../models/prometheus-alerts';
11fdf7f2 11import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
11fdf7f2
TL
12
13@Injectable({
81eedcae 14 providedIn: 'root'
11fdf7f2
TL
15})
16export class PrometheusAlertService {
17 private canAlertsBeNotified = false;
494da23a 18 alerts: AlertmanagerAlert[] = [];
9f95a23c 19 rules: PrometheusRule[] = [];
cd265ab1 20 activeAlerts: number;
11fdf7f2
TL
21
22 constructor(
23 private alertFormatter: PrometheusAlertFormatter,
24 private prometheusService: PrometheusService
25 ) {}
26
9f95a23c 27 getAlerts() {
494da23a
TL
28 this.prometheusService.ifAlertmanagerConfigured(() => {
29 this.prometheusService.getAlerts().subscribe(
30 (alerts) => this.handleAlerts(alerts),
31 (resp) => {
32 if ([404, 504].includes(resp.status)) {
33 this.prometheusService.disableAlertmanagerConfig();
11fdf7f2 34 }
494da23a
TL
35 }
36 );
11fdf7f2
TL
37 });
38 }
39
9f95a23c
TL
40 getRules() {
41 this.prometheusService.ifPrometheusConfigured(() => {
42 this.prometheusService.getRules('alerting').subscribe((groups) => {
43 this.rules = groups['groups'].reduce((acc, group) => {
44 return acc.concat(
45 group.rules.map((rule) => {
46 rule.group = group.name;
47 return rule;
48 })
49 );
50 }, []);
51 });
52 });
53 }
54
55 refresh() {
56 this.getAlerts();
57 this.getRules();
58 }
59
494da23a 60 private handleAlerts(alerts: AlertmanagerAlert[]) {
11fdf7f2
TL
61 if (this.canAlertsBeNotified) {
62 this.notifyOnAlertChanges(alerts, this.alerts);
63 }
cd265ab1
TL
64 this.activeAlerts = _.reduce<AlertmanagerAlert, number>(
65 this.alerts,
66 (result, alert) => (alert.status.state === 'active' ? ++result : result),
67 0
68 );
11fdf7f2
TL
69 this.alerts = alerts;
70 this.canAlertsBeNotified = true;
71 }
72
494da23a 73 private notifyOnAlertChanges(alerts: AlertmanagerAlert[], oldAlerts: AlertmanagerAlert[]) {
11fdf7f2
TL
74 const changedAlerts = this.getChangedAlerts(
75 this.alertFormatter.convertToCustomAlerts(alerts),
76 this.alertFormatter.convertToCustomAlerts(oldAlerts)
77 );
78 const notifications = changedAlerts.map((alert) =>
79 this.alertFormatter.convertAlertToNotification(alert)
80 );
81 this.alertFormatter.sendNotifications(notifications);
82 }
83
84 private getChangedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
85 const updatedAndNew = _.differenceWith(alerts, oldAlerts, _.isEqual);
86 return updatedAndNew.concat(this.getVanishedAlerts(alerts, oldAlerts));
87 }
88
89 private getVanishedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
90 return _.differenceWith(oldAlerts, alerts, (a, b) => a.fingerprint === b.fingerprint).map(
91 (alert) => {
92 alert.status = 'resolved';
93 return alert;
94 }
95 );
96 }
97}