From: Afreen Misbah Date: Tue, 21 Jul 2026 17:31:31 +0000 (+0530) Subject: mgr/dashboard: add view alerts button in data resiliency tab X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0f2fd79457f3c2565f1379832b93f2d45715c59c;p=ceph.git mgr/dashboard: add view alerts button in data resiliency tab Signed-off-by: Afreen Misbah --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/health-card/overview-health-card.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/health-card/overview-health-card.component.html index d171c4a6d95..80be6845654 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/health-card/overview-health-card.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/overview/health-card/overview-health-card.component.html @@ -2,6 +2,7 @@ @let hwEnabled = enabled$ | async; @let hwData = hardwareData$ | async; @let telemetryEnabled = telemetryEnabled$ | async; +@let pgAlertCount = pgAlertCount$ | async; @let colorClass = 'overview-health-card-status--' + vm?.clusterHealth?.icon; @@ -357,19 +358,33 @@

{{ vm?.resiliencyHealth?.description }}

- + See all PGs states + + + @if (vm?.pgs?.activeCleanChartData && vm?.pgs?.activeCleanChartOptions) {
@@ -381,7 +396,7 @@

Data resiliency reflects data availability and replication (% of placement groups that are active and clean). @@ -404,8 +419,8 @@ ) { @if (item.count) {

{{ item?.state }}: (); @@ -146,6 +148,8 @@ export class OverviewHealthCardComponent { shareReplay({ bufferSize: 1, refCount: true }) ); + readonly pgAlertCount$ = this.prometheusAlertService.pgAlerts$.pipe(startWith(0)); + readonly telemetryEnabled$: Observable = this.healthService.getTelemetryStatus().pipe( map((enabled: any) => !!enabled), catchError(() => of(false)), diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts index 24429e46f02..273d5d87249 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts @@ -120,6 +120,7 @@ import Plug16 from '@carbon/icons/es/plug/16'; import VmdkDisk16 from '@carbon/icons/es/vmdk-disk/16'; import WarningAlt16 from '@carbon/icons/es/warning--alt/16'; import CheckMarkOutline16 from '@carbon/icons/es/checkmark--outline/16'; +import ArrowRight16 from '@carbon/icons/es/arrow--right/16'; import ArrowUpRight16 from '@carbon/icons/es/arrow--up-right/16'; import InProgress16 from '@carbon/icons/es/in-progress/16'; import ArrowDown16 from '@carbon/icons/es/arrow--down/16'; @@ -318,6 +319,7 @@ export class ComponentsModule { VmdkDisk16, WarningAlt16, CheckMarkOutline16, + ArrowRight16, ArrowUpRight16, InProgress16, ArrowDown16, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts index fbccf2e940e..191f7e00055 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/enum/icons.enum.ts @@ -120,6 +120,7 @@ export enum Icons { vmdkDisk = 'vmdk-disk', checkMarkOutline = 'checkmark--outline', warningAlt = 'warning--alt', + arrowRight = 'arrow--right', arrowUpRight = 'arrow--up-right', inProgress = 'in-progress', arrowDown = 'arrow--down', @@ -164,6 +165,7 @@ export const ICON_TYPE = { vmdkDisk: 'vmdk-disk', warningAlt: 'warning--alt', checkMarkOutline: 'checkmark--outline', + arrowRight: 'arrow--right', arrowUpRight: ' arrow--up-right', inProgress: 'in-progress', arrowDown: 'arrow--down', diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.spec.ts new file mode 100644 index 00000000000..7fbb8d60904 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.spec.ts @@ -0,0 +1,51 @@ +import { buildHealthCardVM } from './overview'; +import { HealthSnapshotMap } from './health.interface'; + +function makeSnapshot(checks: Record = {}): HealthSnapshotMap { + return { + fsid: 'test-fsid', + health: { status: 'HEALTH_OK', checks, mutes: [] }, + monmap: { num_mons: 3 }, + osdmap: { in: 3, up: 3, num_osds: 3 }, + pgmap: { + pgs_by_state: [{ state_name: 'active+clean', count: 100 }], + num_pools: 1, + bytes_used: 0, + bytes_total: 1000, + num_pgs: 100, + write_bytes_sec: 0, + read_bytes_sec: 0, + recovering_bytes_per_sec: 0 + }, + mgrmap: { num_active: 1, num_standbys: 1 }, + fsmap: { num_active: 0, num_standbys: 0 }, + num_rgw_gateways: 0, + num_iscsi_gateways: { up: 0, down: 0 }, + num_hosts: 3 + } as any; +} + +describe('buildHealthCardVM', () => { + it('should not include pgAlertCount in the VM', () => { + const vm = buildHealthCardVM(makeSnapshot()); + expect('pgAlertCount' in vm).toBe(false); + }); + + it('should build resiliencyHealth from health checks', () => { + const vm = buildHealthCardVM( + makeSnapshot({ + PG_DEGRADED: { + severity: 'HEALTH_WARN', + summary: { message: 'degraded', count: 5 }, + muted: false + } + }) + ); + expect(vm.resiliencyHealth.severity).toBe('warn'); + }); + + it('should report ok resiliency when no PG checks', () => { + const vm = buildHealthCardVM(makeSnapshot()); + expect(vm.resiliencyHealth.severity).toBe('ok'); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.ts index 6bc21f692be..a039533cbac 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/overview.ts @@ -210,8 +210,8 @@ export const SEVERITY = { export const ACTIVE_CLEAN_CHART_OPTIONS: GaugeChartOptions = { resizable: true, - height: '100px', - width: '100px', + height: '130px', + width: '130px', gauge: { type: 'full' }, toolbar: { enabled: false diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts index 4273f8b4f95..bfed174febe 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/prometheus-alert.service.ts @@ -34,6 +34,9 @@ export class PrometheusAlertService { private warningSubject = new BehaviorSubject(0); readonly warningAlerts$ = this.warningSubject.asObservable(); + private pgAlertsSubject = new BehaviorSubject(0); + readonly pgAlerts$ = this.pgAlertsSubject.asObservable(); + constructor( private alertFormatter: PrometheusAlertFormatter, private prometheusService: PrometheusService @@ -117,9 +120,16 @@ export class PrometheusAlertService { 0 ); + const activePgAlerts = alerts.filter( + (alert) => + alert.status.state === AlertState.ACTIVE && + alert.labels.alertname?.startsWith('CephPG') + ).length; + this.totalSubject.next(this.activeAlerts); this.criticalSubject.next(this.activeCriticalAlerts); this.warningSubject.next(this.activeWarningAlerts); + this.pgAlertsSubject.next(activePgAlerts); this.alerts = alerts .reverse()