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 { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
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';
permission: Permission;
selection = new CdTableSelection();
icons = Icons;
- customCss = {
- 'badge badge-danger': 'active',
- 'badge badge-warning': 'unprocessed',
- 'badge badge-info': 'suppressed'
- };
constructor(
// NotificationsComponent will refresh all alerts every 5s (No need to do it here as well)
private authStorageService: AuthStorageService,
public prometheusAlertService: PrometheusAlertService,
private urlBuilder: URLBuilderService,
- private cdDatePipe: CdDatePipe,
@Inject(PrometheusService) prometheusService: PrometheusService
) {
super(prometheusService);
{
name: $localize`Name`,
prop: 'labels.alertname',
+ cellClass: 'font-weight-bold',
flexGrow: 2
},
{
- name: $localize`Job`,
- prop: 'labels.job',
- flexGrow: 2
+ name: $localize`Summary`,
+ prop: 'annotations.summary',
+ flexGrow: 3
},
{
name: $localize`Severity`,
- prop: 'labels.severity'
+ prop: 'labels.severity',
+ flexGrow: 1,
+ cellTransformation: CellTemplate.badge,
+ customTemplateConfig: {
+ map: {
+ critical: { class: 'badge-danger' },
+ warning: { class: 'badge-warning' }
+ }
+ }
},
{
name: $localize`State`,
prop: 'status.state',
- cellTransformation: CellTemplate.classAdding
+ flexGrow: 1,
+ cellTransformation: CellTemplate.badge,
+ customTemplateConfig: {
+ map: {
+ active: { class: 'badge-info' },
+ unprocessed: { class: 'badge-warning' },
+ suppressed: { class: 'badge-dark' }
+ }
+ }
},
{
name: $localize`Started`,
prop: 'startsAt',
- pipe: this.cdDatePipe
+ cellTransformation: CellTemplate.timeAgo,
+ flexGrow: 1
},
{
name: $localize`URL`,
prop: 'generatorURL',
+ flexGrow: 1,
sortable: false,
cellTemplate: this.externalLinkTpl
}
class="nav-tabs">
<li ngbNavItem="/monitoring/active-alerts">
<a ngbNavLink
- i18n>Active Alerts</a>
+ i18n>Active Alerts
+ <small *ngIf="prometheusAlertService.activeCriticalAlerts > 0"
+ class="badge badge-danger ml-1">{{ prometheusAlertService.activeCriticalAlerts }}</small>
+ <small *ngIf="prometheusAlertService.activeWarningAlerts > 0"
+ class="badge badge-warning ml-1">{{ prometheusAlertService.activeWarningAlerts }}</small></a>
</li>
<li ngbNavItem="/monitoring/alerts">
<a ngbNavLink
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
+import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
import { configureTestBed } from '~/testing/unit-test-helper';
import { PrometheusTabsComponent } from './prometheus-tabs.component';
configureTestBed({
imports: [RouterTestingModule, NgbNavModule],
- declarations: [PrometheusTabsComponent]
+ declarations: [PrometheusTabsComponent],
+ providers: [{ provide: PrometheusAlertService, useValue: { alerts: [] } }]
});
beforeEach(() => {
import { Component } from '@angular/core';
import { Router } from '@angular/router';
+import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
+
@Component({
selector: 'cd-prometheus-tabs',
templateUrl: './prometheus-tabs.component.html',
styleUrls: ['./prometheus-tabs.component.scss']
})
export class PrometheusTabsComponent {
- constructor(public router: Router) {}
+ constructor(public router: Router, public prometheusAlertService: PrometheusAlertService) {}
}
import { Component, Inject, OnInit } from '@angular/core';
+import _ from 'lodash';
+
import { PrometheusService } from '~/app/shared/api/prometheus.service';
+import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
+import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
import { PrometheusRule } from '~/app/shared/models/prometheus-alerts';
import { DurationPipe } from '~/app/shared/pipes/duration.pipe';
import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
export class RulesListComponent extends PrometheusListHelper implements OnInit {
columns: CdTableColumn[];
expandedRow: PrometheusRule;
+ selection = new CdTableSelection();
/**
* Hide active alerts in details of alerting rules as they are already shown
ngOnInit() {
super.ngOnInit();
this.columns = [
- { prop: 'name', name: $localize`Name` },
- { prop: 'labels.severity', name: $localize`Severity` },
- { prop: 'group', name: $localize`Group` },
- { prop: 'duration', name: $localize`Duration`, pipe: new DurationPipe() },
- { prop: 'query', name: $localize`Query`, isHidden: true },
- { prop: 'annotations.description', name: $localize`Description` }
+ { prop: 'name', name: $localize`Name`, cellClass: 'font-weight-bold', flexGrow: 2 },
+ {
+ prop: 'labels.severity',
+ name: $localize`Severity`,
+ flexGrow: 1,
+ cellTransformation: CellTemplate.badge,
+ customTemplateConfig: {
+ map: {
+ critical: { class: 'badge-danger' },
+ warning: { class: 'badge-warning' }
+ }
+ }
+ },
+ {
+ prop: 'group',
+ name: $localize`Group`,
+ flexGrow: 1,
+ cellTransformation: CellTemplate.badge
+ },
+ { prop: 'duration', name: $localize`Duration`, pipe: new DurationPipe(), flexGrow: 1 },
+ { prop: 'query', name: $localize`Query`, isHidden: true, flexGrow: 1 },
+ { prop: 'annotations.summary', name: $localize`Summary`, flexGrow: 3 }
];
}
+
+ updateSelection(selection: CdTableSelection) {
+ this.selection = selection;
+ }
}
*ngIf="permissions.prometheus.read">
<a routerLink="/monitoring">
<ng-container i18n>Monitoring</ng-container>
- <small *ngIf="prometheusAlertService.activeAlerts > 0"
- class="badge badge-danger">{{ prometheusAlertService.activeAlerts }}</small>
+ <small *ngIf="prometheusAlertService.activeCriticalAlerts > 0"
+ class="badge badge-danger ml-1">{{ prometheusAlertService.activeCriticalAlerts }}</small>
+ <small *ngIf="prometheusAlertService.activeWarningAlerts > 0"
+ class="badge badge-warning ml-1">{{ prometheusAlertService.activeWarningAlerts }}</small>
</a>
</li>
</ul>
(click)="toggleExpandRow(row, isExpanded, $event)">
</a>
</ng-template>
+
+<ng-template #timeAgoTpl
+ let-value="value">
+ <span data-toggle="tooltip"
+ [title]="value | cdDate">{{ value | relativeDate }}</span>
+</ng-template>
mapTpl: TemplateRef<any>;
@ViewChild('truncateTpl', { static: true })
truncateTpl: TemplateRef<any>;
+ @ViewChild('timeAgoTpl', { static: true })
+ timeAgoTpl: TemplateRef<any>;
@ViewChild('rowDetailsTpl', { static: true })
rowDetailsTpl: TemplateRef<any>;
this.cellTemplates.badge = this.badgeTpl;
this.cellTemplates.map = this.mapTpl;
this.cellTemplates.truncate = this.truncateTpl;
+ this.cellTemplates.timeAgo = this.timeAgoTpl;
}
useCustomClass(value: any): string {
// omission?: string; // Defaults to empty string.
// }
// }
- truncate = 'truncate'
+ truncate = 'truncate',
+ /*
+ This templace replaces a time, datetime or timestamp with a user-friendly "X {seconds,minutes,hours,days,...} ago",
+ but the tooltip still displays the absolute timestamp
+ */
+ timeAgo = 'timeAgo'
}
alerts: AlertmanagerAlert[] = [];
rules: PrometheusRule[] = [];
activeAlerts: number;
+ activeCriticalAlerts: number;
+ activeWarningAlerts: number;
constructor(
private alertFormatter: PrometheusAlertFormatter,
(result, alert) => (alert.status.state === 'active' ? ++result : result),
0
);
+ this.activeCriticalAlerts = _.reduce<AlertmanagerAlert, number>(
+ this.alerts,
+ (result, alert) =>
+ alert.status.state === 'active' && alert.labels.severity === 'critical' ? ++result : result,
+ 0
+ );
+ this.activeWarningAlerts = _.reduce<AlertmanagerAlert, number>(
+ this.alerts,
+ (result, alert) =>
+ alert.status.state === 'active' && alert.labels.severity === 'warning' ? ++result : result,
+ 0
+ );
this.alerts = alerts;
this.canAlertsBeNotified = true;
}