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