1 import { Injectable } from '@angular/core';
3 import _ from 'lodash';
5 import { PrometheusService } from '../api/prometheus.service';
10 } from '../models/prometheus-alerts';
11 import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
16 export class PrometheusAlertService {
17 private canAlertsBeNotified = false;
18 alerts: AlertmanagerAlert[] = [];
19 rules: PrometheusRule[] = [];
21 activeCriticalAlerts: number;
22 activeWarningAlerts: number;
25 private alertFormatter: PrometheusAlertFormatter,
26 private prometheusService: PrometheusService
30 this.prometheusService.ifAlertmanagerConfigured(() => {
31 this.prometheusService.getAlerts().subscribe(
32 (alerts) => this.handleAlerts(alerts),
34 if ([404, 504].includes(resp.status)) {
35 this.prometheusService.disableAlertmanagerConfig();
43 this.prometheusService.ifPrometheusConfigured(() => {
44 this.prometheusService.getRules('alerting').subscribe((groups) => {
45 this.rules = groups['groups'].reduce((acc, group) => {
47 group.rules.map((rule) => {
48 rule.group = group.name;
62 private handleAlerts(alerts: AlertmanagerAlert[]) {
63 if (this.canAlertsBeNotified) {
64 this.notifyOnAlertChanges(alerts, this.alerts);
66 this.activeAlerts = _.reduce<AlertmanagerAlert, number>(
68 (result, alert) => (alert.status.state === 'active' ? ++result : result),
71 this.activeCriticalAlerts = _.reduce<AlertmanagerAlert, number>(
74 alert.status.state === 'active' && alert.labels.severity === 'critical' ? ++result : result,
77 this.activeWarningAlerts = _.reduce<AlertmanagerAlert, number>(
80 alert.status.state === 'active' && alert.labels.severity === 'warning' ? ++result : result,
84 this.canAlertsBeNotified = true;
87 private notifyOnAlertChanges(alerts: AlertmanagerAlert[], oldAlerts: AlertmanagerAlert[]) {
88 const changedAlerts = this.getChangedAlerts(
89 this.alertFormatter.convertToCustomAlerts(alerts),
90 this.alertFormatter.convertToCustomAlerts(oldAlerts)
92 const suppressedFiltered = _.filter(changedAlerts, (alert) => {
93 return alert.status !== 'suppressed';
95 const notifications = suppressedFiltered.map((alert) =>
96 this.alertFormatter.convertAlertToNotification(alert)
98 this.alertFormatter.sendNotifications(notifications);
101 private getChangedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
102 const updatedAndNew = _.differenceWith(alerts, oldAlerts, _.isEqual);
103 return updatedAndNew.concat(this.getVanishedAlerts(alerts, oldAlerts));
106 private getVanishedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
107 return _.differenceWith(oldAlerts, alerts, (a, b) => a.fingerprint === b.fingerprint).map(
109 alert.status = 'resolved';