From 30b8ca4a1a246a6ebaba0b90b8f5726581d88420 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Thu, 19 Mar 2026 10:45:55 +0100 Subject: [PATCH 1/3] further clarify plot titles --- web/frontend/src/status/DashInternal.svelte | 2 +- web/frontend/src/status/dashdetails/StatusDash.svelte | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/frontend/src/status/DashInternal.svelte b/web/frontend/src/status/DashInternal.svelte index 35ba6e9b..5495e170 100644 --- a/web/frontend/src/status/DashInternal.svelte +++ b/web/frontend/src/status/DashInternal.svelte @@ -577,7 +577,7 @@ xlabel="Time" ylabel="Nodes" yunit = "#Count" - title = "Health States" + title = "Metric Health" stateType = "Health" /> {/key} diff --git a/web/frontend/src/status/dashdetails/StatusDash.svelte b/web/frontend/src/status/dashdetails/StatusDash.svelte index 46768502..82bdf75f 100644 --- a/web/frontend/src/status/dashdetails/StatusDash.svelte +++ b/web/frontend/src/status/dashdetails/StatusDash.svelte @@ -409,14 +409,14 @@
{#key $statesTimed?.data?.healthStates}

- {cluster.charAt(0).toUpperCase() + cluster.slice(1)} Health States Over Time + {cluster.charAt(0).toUpperCase() + cluster.slice(1)} Metric Health Over Time

{/key} From 22057ff281f30d5c8952b10e5924203fd9287cc0 Mon Sep 17 00:00:00 2001 From: Jan Eitzinger Date: Thu, 19 Mar 2026 11:04:32 +0100 Subject: [PATCH 2/3] Pass reqKey as CacheKey Entire-Checkpoint: b95ef43221bb --- internal/graph/schema.resolvers.go | 4 ++-- internal/graph/stats_cache.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/graph/schema.resolvers.go b/internal/graph/schema.resolvers.go index 3e923696..adbc5f80 100644 --- a/internal/graph/schema.resolvers.go +++ b/internal/graph/schema.resolvers.go @@ -676,10 +676,10 @@ func (r *queryResolver) JobsStatistics(ctx context.Context, filter []*model.JobF // Use request-scoped cache: multiple aliases with same (filter, groupBy) // but different sortBy/page hit the DB only once. if cache := getStatsGroupCache(ctx); cache != nil { - key := statsCacheKey(filter, groupBy) + key := statsCacheKey(filter, groupBy, reqFields) var allStats []*model.JobsStatistics allStats, err = cache.getOrCompute(key, func() ([]*model.JobsStatistics, error) { - return r.Repo.JobsStatsGrouped(ctx, filter, nil, nil, groupBy, nil) + return r.Repo.JobsStatsGrouped(ctx, filter, nil, nil, groupBy, reqFields) }) if err == nil { stats = sortAndPageStats(allStats, sortBy, page) diff --git a/internal/graph/stats_cache.go b/internal/graph/stats_cache.go index 2dbb5ca5..92e8e85b 100644 --- a/internal/graph/stats_cache.go +++ b/internal/graph/stats_cache.go @@ -53,9 +53,9 @@ func getStatsGroupCache(ctx context.Context) *statsGroupCache { return nil } -// cacheKey builds a deterministic string key from filter + groupBy. -func statsCacheKey(filter []*model.JobFilter, groupBy *model.Aggregate) string { - return fmt.Sprintf("%v|%v", filter, *groupBy) +// cacheKey builds a deterministic string key from filter + groupBy + reqFields. +func statsCacheKey(filter []*model.JobFilter, groupBy *model.Aggregate, reqFields map[string]bool) string { + return fmt.Sprintf("%v|%v|%v", filter, *groupBy, reqFields) } // getOrCompute returns cached results for the given key, computing them on From c42898bd999695c05530fe1cb663a167632fc0a7 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Thu, 19 Mar 2026 11:31:40 +0100 Subject: [PATCH 3/3] fix: add top list query fixes to analysis and dashboard --- web/frontend/src/Analysis.root.svelte | 14 ++++++++++--- web/frontend/src/status/DashInternal.svelte | 21 +++++++++++-------- .../src/status/dashdetails/UsageDash.svelte | 2 -- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/web/frontend/src/Analysis.root.svelte b/web/frontend/src/Analysis.root.svelte index f8ca1f3b..4392f972 100644 --- a/web/frontend/src/Analysis.root.svelte +++ b/web/frontend/src/Analysis.root.svelte @@ -187,6 +187,12 @@ }) ); + const topListData = $derived( + $topQuery?.data?.topList + ?.toSorted((a, b) => b[sortSelection.key] - a[sortSelection.key]) + .slice(0, 10) ?? [], + ); + // Note: Different footprints than those saved in DB per Job -> Caused by Legacy Naming let footprintsQuery = $derived( queryStore({ @@ -424,10 +430,12 @@ canvasId={`pie-${groupSelection.key}`} size={colWidth1 / 1.9} sliceLabel={sortSelection.label} - quantities={$topQuery.data.topList.map( + quantities={topListData.map( (t) => t[sortSelection.key], )} - entities={$topQuery.data.topList.map((t) => scrambleNames ? scramble(t.id) : t.id)} + entities={topListData.map((t) => + scrambleNames ? scramble(t.id) : t.id) + } /> {/if} {/key} @@ -454,7 +462,7 @@ - {#each $topQuery.data.topList as te, i} + {#each topListData as te, i} {#if groupSelection.key == "user"} diff --git a/web/frontend/src/status/DashInternal.svelte b/web/frontend/src/status/DashInternal.svelte index 5495e170..326d49bf 100644 --- a/web/frontend/src/status/DashInternal.svelte +++ b/web/frontend/src/status/DashInternal.svelte @@ -53,7 +53,6 @@ const useCbColors = getContext("cc-config")?.plotConfiguration_colorblindMode || false /* States */ - let pagingState = $state({page: 1, itemsPerPage: 10}) // Top 10 let from = $state(new Date(Date.now() - 5 * 60 * 1000)); let clusterFrom = $state(new Date(Date.now() - (8 * 60 * 60 * 1000))); let to = $state(new Date(Date.now())); @@ -201,11 +200,9 @@ query: gql` query ( $filter: [JobFilter!]! - $paging: PageRequest! ) { jobsStatistics( filter: $filter - page: $paging sortBy: TOTALJOBS groupBy: PROJECT ) { @@ -215,12 +212,17 @@ } `, variables: { - filter: [{ cluster: { eq: presetCluster} }, { state: ["running"] }], - paging: pagingState // Top 10 + filter: [{ cluster: { eq: presetCluster} }, { state: ["running"] }] }, requestPolicy: "network-only" })); + const topProjectJobs = $derived( + $topJobsQuery?.data?.jobsStatistics + ?.toSorted((a, b) => b.totalJobs - a.totalJobs) + .slice(0, 10) ?? [], + ); + const clusterInfo = $derived.by(() => { let rawInfos = {}; if ($initq?.data?.clusters) { @@ -365,7 +367,6 @@ from = new Date(Date.now() - 5 * 60 * 1000); to = new Date(Date.now()); clusterFrom = new Date(Date.now() - (8 * 60 * 60 * 1000)) - pagingState = { page:1, itemsPerPage: 10 }; if (interval) stackedFrom += Math.floor(interval / 1000); else stackedFrom += 1 // Workaround: TimeSelection not linked, just trigger new data on manual refresh @@ -490,10 +491,12 @@ canvasId="hpcpie-jobs-projects" size={colWidthJobs * 0.75} sliceLabel={'Jobs'} - quantities={$topJobsQuery.data.jobsStatistics.map( + quantities={topProjectJobs.map( (tp) => tp['totalJobs'], )} - entities={$topJobsQuery.data.jobsStatistics.map((tp) => scrambleNames ? scramble(tp.id) : tp.id)} + entities={topProjectJobs.map((tp) => + scrambleNames ? scramble(tp.id) : tp.id) + } />
@@ -504,7 +507,7 @@ Project Jobs - {#each $topJobsQuery.data.jobsStatistics as tp, i} + {#each topProjectJobs as tp, i} diff --git a/web/frontend/src/status/dashdetails/UsageDash.svelte b/web/frontend/src/status/dashdetails/UsageDash.svelte index 1d14bed4..33701e50 100644 --- a/web/frontend/src/status/dashdetails/UsageDash.svelte +++ b/web/frontend/src/status/dashdetails/UsageDash.svelte @@ -45,7 +45,6 @@ const durationBinOptions = ["1m", "10m", "1h", "6h", "12h"]; /* State Init */ - let pagingState = $state({ page: 1, itemsPerPage: 10 }); // Top 10 let selectedHistograms = $state([]); // Dummy For Refresh let colWidthJobs = $state(0); let colWidthNodes = $state(0); @@ -208,7 +207,6 @@ { - pagingState = { page: 1, itemsPerPage: 10 }; selectedHistograms = [...$state.snapshot(selectedHistograms)]; }} />