import _ from 'lodash';
import { BehaviorSubject, EMPTY, Observable, Subject, Subscription, of } from 'rxjs';
-import { catchError, exhaustMap, switchMap, take, takeUntil } from 'rxjs/operators';
+import { catchError, exhaustMap, switchMap, takeUntil } from 'rxjs/operators';
import { HealthService } from '~/app/shared/api/health.service';
-import { OsdService } from '~/app/shared/api/osd.service';
-import { PrometheusService } from '~/app/shared/api/prometheus.service';
-import { Promqls as queries } from '~/app/shared/enum/dashboard-promqls.enum';
+import { PrometheusService, PromqlGuageMetric } from '~/app/shared/api/prometheus.service';
+import {
+ CapacityCardQueries,
+ UtilizationCardQueries
+} from '~/app/shared/enum/dashboard-promqls.enum';
import { Icons } from '~/app/shared/enum/icons.enum';
import { DashboardDetails } from '~/app/shared/models/cd-details';
import { Permissions } from '~/app/shared/models/permissions';
import { AlertClass } from '~/app/shared/enum/health-icon.enum';
import { HardwareService } from '~/app/shared/api/hardware.service';
import { SettingsService } from '~/app/shared/api/settings.service';
-import { OsdSettings } from '~/app/shared/models/osd-settings';
import {
IscsiMap,
MdsMap,
PgStatus
} from '~/app/shared/models/health.interface';
+type CapacityCardData = {
+ osdNearfull: number;
+ osdFull: number;
+};
+
@Component({
selector: 'cd-dashboard-v3',
templateUrl: './dashboard-v3.component.html',
})
export class DashboardV3Component extends PrometheusListHelper implements OnInit, OnDestroy {
detailsCardData: DashboardDetails = {};
- osdSettingsService: any;
- osdSettings = new OsdSettings();
+ capacityCardData: CapacityCardData = {
+ osdNearfull: null,
+ osdFull: null
+ };
+ interval = new Subscription();
permissions: Permissions;
enabledFeature$: FeatureTogglesMap$;
color: string;
constructor(
private summaryService: SummaryService,
private orchestratorService: OrchestratorService,
- private osdService: OsdService,
private authStorageService: AuthStorageService,
private featureToggles: FeatureTogglesService,
private healthService: HealthService,
ngOnInit() {
super.ngOnInit();
if (this.permissions.configOpt.read) {
- this.getOsdSettings();
this.isHardwareEnabled$ = this.getHardwareConfig();
this.hardwareSummary$ = this.hardwareSubject.pipe(
switchMap(() =>
this.getPrometheusData(this.prometheusService.lastHourDateObject);
this.getDetailsCardData();
this.getTelemetryReport();
+ this.getCapacityCardData();
this.prometheusAlertService.getAlerts(true);
}
);
}
- private getOsdSettings() {
- this.osdSettingsService = this.osdService
- .getOsdSettings()
- .pipe(take(1))
- .subscribe((data: OsdSettings) => {
- this.osdSettings = data;
- });
- }
-
public getPrometheusData(selectedTime: any) {
- this.queriesResults = this.prometheusService.getPrometheusQueriesData(
+ this.queriesResults = this.prometheusService.getRangeQueriesData(
selectedTime,
- queries,
+ UtilizationCardQueries,
this.queriesResults
);
}
+ getCapacityQueryValues(data: PromqlGuageMetric['result']) {
+ let osdFull = null;
+ let osdNearfull = null;
+ if (data?.[0]?.metric?.['__name__'] === CapacityCardQueries.OSD_FULL) {
+ osdFull = data[0]?.value?.[1];
+ osdNearfull = data[1]?.value?.[1];
+ } else {
+ osdFull = data?.[1]?.value?.[1];
+ osdNearfull = data?.[0]?.value?.[1];
+ }
+ return [osdFull, osdNearfull];
+ }
+
+ getCapacityCardData() {
+ const CAPACITY_QUERY = `{__name__=~"${CapacityCardQueries.OSD_FULL}|${CapacityCardQueries.OSD_NEARFULL}"}`;
+ this.prometheusService
+ .getGaugeQueryData(CAPACITY_QUERY)
+ .subscribe((data: PromqlGuageMetric) => {
+ const [osdFull, osdNearfull] = this.getCapacityQueryValues(data?.result);
+ this.capacityCardData.osdFull = this.prometheusService.formatGuageMetric(osdFull);
+ this.capacityCardData.osdNearfull = this.prometheusService.formatGuageMetric(osdNearfull);
+ });
+ }
+
private getTelemetryReport() {
this.healthService.getTelemetryStatus().subscribe((enabled: boolean) => {
this.telemetryEnabled = enabled;
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { Observable, Subscription, forkJoin, timer } from 'rxjs';
-import { map, switchMap } from 'rxjs/operators';
+import { Observable, Subscription, forkJoin, of, timer } from 'rxjs';
+import { catchError, map, switchMap } from 'rxjs/operators';
import { AlertmanagerSilence } from '../models/alertmanager-silence';
import {
} from '../models/prometheus-alerts';
import moment from 'moment';
+export type PromethuesGaugeMetricResult = {
+ metric: Record<string, string>; // metric metadata
+ value: [number, string]; // timestamp, value
+};
+
+export type PromqlGuageMetric = {
+ resultType: 'vector';
+ result: PromethuesGaugeMetricResult[];
+};
+
@Injectable({
providedIn: 'root'
})
}
}
+ // Range Queries
getPrometheusData(params: any): any {
return this.http.get<any>(`${this.baseURL}/data`, { params });
}
+ // Guage Queries
+ getPrometheusQueryData(params: { params: string }): Observable<PromqlGuageMetric> {
+ return this.http.get<any>(`${this.baseURL}/prometheus_query_data`, { params });
+ }
+
ifAlertmanagerConfigured(fn: (value?: string) => void, elseFn?: () => void): void {
this.ifSettingConfigured(this.settingsKey.alertmanager, fn, elseFn);
}
return data.value || data.instance || '';
}
- getPrometheusQueriesData(
- selectedTime: any,
- queries: any,
- queriesResults: any,
- checkNan?: boolean
- ) {
+ getGaugeQueryData(query: string): Observable<PromqlGuageMetric> {
+ return this.getPrometheusQueryData({ params: query }).pipe(
+ map((result: PromqlGuageMetric) => result),
+ catchError(() => of({ result: [] } as PromqlGuageMetric))
+ );
+ }
+
+ formatGuageMetric(data: string): number {
+ const value: number = parseFloat(data ?? '');
+ // Guage value can be "Nan", "+inf", "-inf" in case of errors
+ return isFinite(value) ? value : null;
+ }
+
+ getRangeQueriesData(selectedTime: any, queries: any, queriesResults: any, checkNan?: boolean) {
this.ifPrometheusConfigured(() => {
if (this.timerGetPrometheusDataSub) {
this.timerGetPrometheusDataSub.unsubscribe();