From 2f7ef05edacce8b40e625661f542760c9590f382 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 5 Dec 2025 17:50:34 +0100 Subject: [PATCH] Enhancement: Update DashboardAnalyticsAggregator and PanelPerformanceMetrics for improved performance metrics handling This commit enhances the DashboardAnalyticsAggregator by ensuring a fresh Subject is created for each dashboard initialization, improving subscription management. Additionally, it updates the PanelPerformanceMetrics component to utilize internationalization for metric labels, enhancing user experience and accessibility. --- .../scene/PanelPerformanceMetrics.tsx | 13 +++++++------ .../services/DashboardAnalyticsAggregator.ts | 14 ++++++++++---- public/locales/en-US/grafana.json | 7 +++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/public/app/features/dashboard-scene/scene/PanelPerformanceMetrics.tsx b/public/app/features/dashboard-scene/scene/PanelPerformanceMetrics.tsx index 17b25b292d0..cd15ae84927 100644 --- a/public/app/features/dashboard-scene/scene/PanelPerformanceMetrics.tsx +++ b/public/app/features/dashboard-scene/scene/PanelPerformanceMetrics.tsx @@ -2,6 +2,7 @@ import { css } from '@emotion/css'; import { useEffect, useRef, useState } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; +import { t } from '@grafana/i18n'; import { SceneComponentProps, SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes'; import { Icon, PanelChrome, Stack, Tooltip, useStyles2 } from '@grafana/ui'; @@ -128,7 +129,6 @@ function PanelPerformanceMetricsRenderer({ model }: SceneComponentProps { return (
- {/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */} {label}: {formatDuration(current)}
); @@ -139,12 +139,13 @@ function PanelPerformanceMetricsRenderer({ model }: SceneComponentProps - {renderMetricRow('Query', lastQueryTime)} - {hasTransformations && renderMetricRow('Transform', lastTransformTime)} - {renderMetricRow('Render', lastRenderTime)} + {renderMetricRow(t('dashboard-scene.panel-performance-metrics.query', 'Query'), lastQueryTime)} + {hasTransformations && + renderMetricRow(t('dashboard-scene.panel-performance-metrics.transform', 'Transform'), lastTransformTime)} + {renderMetricRow(t('dashboard-scene.panel-performance-metrics.render', 'Render'), lastRenderTime)}
- {/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */} - Total: {formatDuration(lastTotalTime)} + {t('dashboard-scene.panel-performance-metrics.total-time', 'Total time')}:{' '} + {formatDuration(lastTotalTime)}
); diff --git a/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts b/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts index 4d77db37b87..674b0a17a3b 100644 --- a/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts +++ b/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts @@ -63,6 +63,12 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo this.panelMetrics.clear(); this.dashboardUID = uid; this.dashboardTitle = title; + // Recreate the Subject for the new dashboard (since this is a singleton, we need a fresh Subject) + // Complete the old Subject first to clean up any remaining subscriptions + if (!this.panelMetricsSubject.closed) { + this.panelMetricsSubject.complete(); + } + this.panelMetricsSubject = new Subject<{ panelId: string; metrics: PanelAnalyticsMetrics }>(); } public destroy() { @@ -70,8 +76,8 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo this.panelMetrics.clear(); this.dashboardUID = ''; this.dashboardTitle = ''; - // Complete the subject to clean up subscriptions - this.panelMetricsSubject.complete(); + // Note: We don't complete the Subject here since this is a singleton that will be reused. + // The Subject will be recreated in initialize() for the next dashboard. } /** @@ -138,7 +144,7 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo // Panel-level events onPanelOperationStart = (data: performanceUtils.PanelPerformanceData): void => { // Start events don't need aggregation, just ensure panel exists - this.ensurePanelExists(data.panelKey, data.panelId, data.pluginId, data.pluginVersion); + this.ensurePanelExists(data.panelKey, String(data.panelId), data.pluginId, data.pluginVersion); }; onPanelOperationComplete = (data: performanceUtils.PanelPerformanceData): void => { @@ -194,7 +200,7 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo break; } - this.panelMetricsSubject.next({ panelId: data.panelId, metrics: panel }); + this.panelMetricsSubject.next({ panelId: String(data.panelId), metrics: panel }); }; // Query-level events diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 6ee3b9e50e6..d355144b1cf 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -6231,6 +6231,12 @@ } } }, + "panel-performance-metrics": { + "query": "Query", + "render": "Render", + "total-time": "Total time", + "transform": "Transform" + }, "panel-viz-type-picker": { "button": { "close": "Back" @@ -9397,6 +9403,7 @@ "toggle-panel-edit": "Toggle panel edit view", "toggle-panel-fullscreen": "Toggle panel fullscreen view", "toggle-panel-legend": "Toggle panel legend", + "toggle-performance-metrics": "Toggle performance metrics", "zoom-in-time-range": "Zoom in time range", "zoom-out-time-range": "Zoom out time range" },