From b25abc5f16addbd4839bb1ce4db87be9b97a3c82 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Wed, 28 Jan 2026 16:50:27 +0100 Subject: [PATCH 1/2] fix selectedMEtric presets in jobList - remove conflicting reactivity --- web/frontend/src/Jobs.root.svelte | 35 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/web/frontend/src/Jobs.root.svelte b/web/frontend/src/Jobs.root.svelte index 2becea35..a34e8727 100644 --- a/web/frontend/src/Jobs.root.svelte +++ b/web/frontend/src/Jobs.root.svelte @@ -52,17 +52,24 @@ let sorting = $state({ field: "startTime", type: "col", order: "DESC" }); /* Derived */ - const presetProject = $derived(filterPresets?.project ? filterPresets.project : ""); + let presetProject = $derived(filterPresets?.project ? filterPresets.project : ""); let selectedCluster = $derived(filterPresets?.cluster ? filterPresets.cluster : null); let selectedSubCluster = $derived(filterPresets?.partition ? filterPresets.partition : null); - let metrics = $derived(filterPresets.cluster - ? filterPresets.partition - ? ccconfig[`metricConfig_jobListMetrics:${filterPresets.cluster}:${filterPresets.partition}`] - : ccconfig[`metricConfig_jobListMetrics:${filterPresets.cluster}`] || ccconfig.metricConfig_jobListMetrics - : ccconfig.metricConfig_jobListMetrics - ); - let showFootprint = $derived(filterPresets.cluster - ? !!ccconfig[`jobList_showFootprint:${filterPresets.cluster}`] + let metrics = $derived.by(() => { + if (selectedCluster) { + if (selectedSubCluster) { + return ccconfig[`metricConfig_jobListMetrics:${selectedCluster}:${selectedSubCluster}`] || + ccconfig[`metricConfig_jobListMetrics:${selectedCluster}`] || + ccconfig.metricConfig_jobListMetrics + } + return ccconfig[`metricConfig_jobListMetrics:${selectedCluster}`] || + ccconfig.metricConfig_jobListMetrics + } + return ccconfig.metricConfig_jobListMetrics + }); + + let showFootprint = $derived(selectedCluster + ? !!ccconfig[`jobList_showFootprint:${selectedCluster}`] : !!ccconfig.jobList_showFootprint ); @@ -83,16 +90,6 @@ }); }); - $effect(() => { - // Load Metric-Selection for last selected cluster - metrics = selectedCluster ? ccconfig[`metricConfig_jobListMetrics:${selectedCluster}`] : ccconfig.metricConfig_jobListMetrics - }); - - $effect(() => { - // Load Metric-Selection for last selected cluster - metrics = selectedSubCluster ? ccconfig[`metricConfig_jobListMetrics:${selectedCluster}:${selectedSubCluster}`] : ccconfig[`metricConfig_jobListMetrics:${selectedCluster}`] - }); - /* On Mount */ // The filterPresets are handled by the Filters component, // so we need to wait for it to be ready before we can start a query. From 7101d2bb3b15256647ff80313fd8bd2eb00e39b6 Mon Sep 17 00:00:00 2001 From: Aditya Ujeniya Date: Wed, 28 Jan 2026 17:47:38 +0100 Subject: [PATCH 2/2] Handle the metric/host not found case differently --- pkg/metricstore/api.go | 20 ++++++++++++++++---- pkg/metricstore/metricstore.go | 2 +- web/frontend/package-lock.json | 26 ++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/pkg/metricstore/api.go b/pkg/metricstore/api.go index a72c2ac7..f0f3bb3c 100644 --- a/pkg/metricstore/api.go +++ b/pkg/metricstore/api.go @@ -18,6 +18,8 @@ import ( ) var ( + // ErrNoHostOrMetric is returned when the metric store does not find the host or the metric + ErrNoHostOrMetric error = errors.New("[METRICSTORE]> [METRICSTORE]> metric or host not found") // ErrInvalidTimeRange is returned when a query has 'from' >= 'to' ErrInvalidTimeRange = errors.New("[METRICSTORE]> invalid time range: 'from' must be before 'to'") // ErrEmptyCluster is returned when a query with ForAllNodes has no cluster specified @@ -278,10 +280,20 @@ func FetchData(req APIQueryRequest) (*APIQueryResponse, error) { data.Data, data.From, data.To, data.Resolution, err = ms.Read(sel, query.Metric, req.From, req.To, query.Resolution) if err != nil { - msg := err.Error() - data.Error = &msg - res = append(res, data) - continue + // Check a special case where only the metric or host. + // Dont send errors, instead just send empty array + // where frontend already renders error for empty array. + if err == ErrNoHostOrMetric { + data.Data = make([]schema.Float, 0) + data.From = req.From + data.To = req.To + data.Resolution = query.Resolution + } else { + msg := err.Error() + data.Error = &msg + res = append(res, data) + continue + } } if req.WithStats { diff --git a/pkg/metricstore/metricstore.go b/pkg/metricstore/metricstore.go index 617e945e..789c6d07 100644 --- a/pkg/metricstore/metricstore.go +++ b/pkg/metricstore/metricstore.go @@ -699,7 +699,7 @@ func (m *MemoryStore) Read(selector util.Selector, metric string, from, to, reso if err != nil { return nil, 0, 0, 0, err } else if n == 0 { - return nil, 0, 0, 0, errors.New("[METRICSTORE]> metric or host not found") + return nil, 0, 0, 0, ErrNoHostOrMetric } else if n > 1 { if minfo.Aggregation == AvgAggregation { normalize := 1. / schema.Float(n) diff --git a/web/frontend/package-lock.json b/web/frontend/package-lock.json index 6962dc1b..e3451242 100644 --- a/web/frontend/package-lock.json +++ b/web/frontend/package-lock.json @@ -250,6 +250,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -263,6 +264,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -276,6 +278,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -289,6 +292,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -302,6 +306,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -315,6 +320,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -328,6 +334,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -341,6 +348,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -354,6 +362,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -367,6 +376,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -380,6 +390,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -393,6 +404,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -406,6 +418,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -419,6 +432,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -432,6 +446,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -445,6 +460,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -458,6 +474,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -471,6 +488,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -484,6 +502,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -497,6 +516,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -510,6 +530,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -523,6 +544,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -536,6 +558,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -549,6 +572,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -562,6 +586,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -812,6 +837,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true,