From 50499fa749511f49f90643d77fcb891fa60ec6f9 Mon Sep 17 00:00:00 2001 From: Oscar Kilhed Date: Fri, 11 Apr 2025 13:56:58 +0200 Subject: [PATCH] Dashboards: Add a config setting that limits the number of series that will be displayed in a panel. Users can opt in to render all series. (#103405) * Limit series in panels in dashboards * fix mangled comment --- conf/defaults.ini | 3 +++ packages/grafana-data/src/types/config.ts | 1 + packages/grafana-runtime/src/config.ts | 1 + pkg/api/dtos/frontend_settings.go | 1 + pkg/api/frontendsettings.go | 1 + pkg/setting/setting.go | 2 ++ .../dashboard-scene/serialization/layoutSerializers/utils.ts | 2 ++ .../dashboard-scene/serialization/transformSaveModelToScene.ts | 1 + public/app/features/dashboard-scene/utils/utils.ts | 1 + 9 files changed, 13 insertions(+) diff --git a/conf/defaults.ini b/conf/defaults.ini index 6997156c517..1678a620278 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -472,6 +472,9 @@ default_home_dashboard_path = # Dashboards UIDs to report performance metrics for. * can be used to report metrics for all dashboards dashboard_performance_metrics = +# Maximum number of series that will be showed in a single panel. Users can opt in to rendering all series. Default is 0 (unlimited). +panel_series_limit = + ################################### Data sources ######################### [datasources] # Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API. diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index dbfbc5eeeb3..3e6de71e8d3 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -227,6 +227,7 @@ export interface GrafanaConfig { rudderstackIntegrationsUrl: string | undefined; analyticsConsoleReporting: boolean; dashboardPerformanceMetrics: string[]; + panelSeriesLimit: number; sqlConnectionLimits: SqlConnectionLimits; sharedWithMeFolderUID?: string; rootFolderUID?: string; diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 8b0beab714f..7031216db7c 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -184,6 +184,7 @@ export class GrafanaBootConfig implements GrafanaConfig { rudderstackIntegrationsUrl: undefined; analyticsConsoleReporting = false; dashboardPerformanceMetrics: string[] = []; + panelSeriesLimit = 0; sqlConnectionLimits = { maxOpenConns: 100, maxIdleConns: 100, diff --git a/pkg/api/dtos/frontend_settings.go b/pkg/api/dtos/frontend_settings.go index b9c66d8de32..16ee4d2ac3d 100644 --- a/pkg/api/dtos/frontend_settings.go +++ b/pkg/api/dtos/frontend_settings.go @@ -194,6 +194,7 @@ type FrontendSettingsDTO struct { AnalyticsConsoleReporting bool `json:"analyticsConsoleReporting"` DashboardPerformanceMetrics []string `json:"dashboardPerformanceMetrics"` + PanelSeriesLimit int `json:"panelSeriesLimit"` FeedbackLinksEnabled bool `json:"feedbackLinksEnabled"` ApplicationInsightsConnectionString string `json:"applicationInsightsConnectionString"` diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index c069cf8cf9a..935455a09c4 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -216,6 +216,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro RudderstackIntegrationsUrl: hs.Cfg.RudderstackIntegrationsURL, AnalyticsConsoleReporting: hs.Cfg.FrontendAnalyticsConsoleReporting, DashboardPerformanceMetrics: hs.Cfg.DashboardPerformanceMetrics, + PanelSeriesLimit: hs.Cfg.PanelSeriesLimit, FeedbackLinksEnabled: hs.Cfg.FeedbackLinksEnabled, ApplicationInsightsConnectionString: hs.Cfg.ApplicationInsightsConnectionString, ApplicationInsightsEndpointUrl: hs.Cfg.ApplicationInsightsEndpointUrl, diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 84df40fd67a..c20b0468699 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -226,6 +226,7 @@ type Cfg struct { MinRefreshInterval string DefaultHomeDashboardPath string DashboardPerformanceMetrics []string + PanelSeriesLimit int // Auth LoginCookieName string @@ -1149,6 +1150,7 @@ func (cfg *Cfg) parseINIFile(iniFile *ini.File) error { cfg.MinRefreshInterval = valueAsString(dashboards, "min_refresh_interval", "5s") cfg.DefaultHomeDashboardPath = dashboards.Key("default_home_dashboard_path").MustString("") cfg.DashboardPerformanceMetrics = util.SplitString(dashboards.Key("dashboard_performance_metrics").MustString("")) + cfg.PanelSeriesLimit = dashboards.Key("panel_series_limit").MustInt(0) if err := readUserSettings(iniFile, cfg); err != nil { return err diff --git a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts index 81c3985f238..48da1b2aa8f 100644 --- a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts +++ b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts @@ -67,6 +67,7 @@ export function buildVizPanel(panel: PanelKind, id?: number): VizPanel { displayMode: panel.spec.transparent ? 'transparent' : 'default', hoverHeader: !panel.spec.title && !timeOverrideShown, hoverHeaderOffset: 0, + seriesLimit: config.panelSeriesLimit, $data: createPanelDataProvider(panel), titleItems, $behaviors: [], @@ -106,6 +107,7 @@ export function buildLibraryPanel(panel: LibraryPanelKind, id?: number): VizPane const vizPanelState: VizPanelState = { key: getVizPanelKeyForPanelId(id ?? panel.spec.id), titleItems, + seriesLimit: config.panelSeriesLimit, $behaviors: [ new LibraryPanelBehavior({ uid: panel.spec.libraryPanel.uid, diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index 0b7435c1fe9..d0418ba94d0 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -322,6 +322,7 @@ export function buildGridItemForPanel(panel: PanelModel): DashboardGridItem { options: panel.options ?? {}, fieldConfig: panel.fieldConfig, pluginVersion: panel.pluginVersion, + seriesLimit: config.panelSeriesLimit, displayMode: panel.transparent ? 'transparent' : undefined, // To be replaced with it's own option persited option instead derived hoverHeader: !panel.title && !timeOverrideShown, diff --git a/public/app/features/dashboard-scene/utils/utils.ts b/public/app/features/dashboard-scene/utils/utils.ts index fff901adb67..e4e302dd652 100644 --- a/public/app/features/dashboard-scene/utils/utils.ts +++ b/public/app/features/dashboard-scene/utils/utils.ts @@ -328,6 +328,7 @@ export function getDefaultVizPanel(): VizPanel { return new VizPanel({ title: newPanelTitle, pluginId: defaultPluginId, + seriesLimit: config.panelSeriesLimit, titleItems: [new VizPanelLinks({ menu: new VizPanelLinksMenu({}) })], hoverHeaderOffset: 0, $behaviors: [],