All files / src/app/shared/services prometheus-alert.service.ts

100% Statements 41/41
71.43% Branches 5/7
100% Functions 12/12
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 748x   8x   8x   8x 8x         8x 13x 13x 13x     13x 13x     13x 13x   13x 12x   1x 1x   1x 1x               8x   6x   12x 12x     8x 6x       6x 5x   6x     8x 6x 6x     8x 10x   2x 2x       8x  
import { Injectable } from '@angular/core';
 
import * as _ from 'lodash';
 
import { PrometheusService } from '../api/prometheus.service';
import { PrometheusAlert, PrometheusCustomAlert } from '../models/prometheus-alerts';
import { PrometheusAlertFormatter } from './prometheus-alert-formatter';
import { ServicesModule } from './services.module';
 
@Injectable({
  providedIn: ServicesModule
})
export class PrometheusAlertService {
  private canAlertsBeNotified = false;
  private connected = true;
  alerts: PrometheusAlert[] = [];
 
  constructor(
    private alertFormatter: PrometheusAlertFormatter,
    private prometheusService: PrometheusService
  ) {}
 
  refresh() {
    this.prometheusService.ifAlertmanagerConfigured((url) => {
      if (this.connected) {
        this.prometheusService.list().subscribe(
          (alerts) => this.handleAlerts(alerts),
          (resp) => {
            const errorMsg = `Please check if <a target="_blank" href="${url}">Prometheus Alertmanager</a> is still running`;
            resp['application'] = 'Prometheus';
            if (resp.status === 500) {
              this.connected = false;
              resp.error.detail = errorMsg;
            }
          }
        );
      }
    });
  }
 
  private handleAlerts(alerts: PrometheusAlert[]) {
    if (this.canAlertsBeNotified) {
      this.notifyOnAlertChanges(alerts, this.alerts);
    }
    this.alerts = alerts;
    this.canAlertsBeNotified = true;
  }
 
  private notifyOnAlertChanges(alerts: PrometheusAlert[], oldAlerts: PrometheusAlert[]) {
    const changedAlerts = this.getChangedAlerts(
      this.alertFormatter.convertToCustomAlerts(alerts),
      this.alertFormatter.convertToCustomAlerts(oldAlerts)
    );
    const notifications = changedAlerts.map((alert) =>
      this.alertFormatter.convertAlertToNotification(alert)
    );
    this.alertFormatter.sendNotifications(notifications);
  }
 
  private getChangedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
    const updatedAndNew = _.differenceWith(alerts, oldAlerts, _.isEqual);
    return updatedAndNew.concat(this.getVanishedAlerts(alerts, oldAlerts));
  }
 
  private getVanishedAlerts(alerts: PrometheusCustomAlert[], oldAlerts: PrometheusCustomAlert[]) {
    return _.differenceWith(oldAlerts, alerts, (a, b) => a.fingerprint === b.fingerprint).map(
      (alert) => {
        alert.status = 'resolved';
        return alert;
      }
    );
  }
}