From d9f9c8aaf51f2a1b46d30c7392fec0094972fee2 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Fri, 3 Nov 2023 17:09:16 +0100 Subject: [PATCH 1/7] fix: retrigger gql api at manual refresh - solves #221 --- web/frontend/src/joblist/JobList.svelte | 2 +- web/frontend/src/joblist/Row.svelte | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/web/frontend/src/joblist/JobList.svelte b/web/frontend/src/joblist/JobList.svelte index 02caf3f4..2484f299 100644 --- a/web/frontend/src/joblist/JobList.svelte +++ b/web/frontend/src/joblist/JobList.svelte @@ -89,7 +89,7 @@ // Force refresh list with existing unchanged variables (== usually would not trigger reactivity) export function refresh() { - queryStore({ + jobs = queryStore({ client: client, query: query, variables: { paging, sorting, filter }, diff --git a/web/frontend/src/joblist/Row.svelte b/web/frontend/src/joblist/Row.svelte index 2117b914..6573b57d 100644 --- a/web/frontend/src/joblist/Row.svelte +++ b/web/frontend/src/joblist/Row.svelte @@ -64,11 +64,12 @@ variables: { id, metrics, scopes } }); - function refresh() { - queryStore({ + export function refresh() { + metricsQuery = queryStore({ client: client, query: query, - variables: { id, metrics, scopes } + variables: { id, metrics, scopes }, + // requestPolicy: 'network-only' // use default cache-first for refresh }); } From bf64fc5213729673eff19a24f5c694b4419bfe27 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Mon, 13 Nov 2023 13:43:44 +0100 Subject: [PATCH 2/7] Add completed state indicator --- web/frontend/src/joblist/JobInfo.svelte | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/web/frontend/src/joblist/JobInfo.svelte b/web/frontend/src/joblist/JobInfo.svelte index 83841c6c..b7ca32ac 100644 --- a/web/frontend/src/joblist/JobInfo.svelte +++ b/web/frontend/src/joblist/JobInfo.svelte @@ -28,6 +28,17 @@ return `${hours}:${('0' + minutes).slice(-2)}:${('0' + seconds).slice(-2)}`; } + function getStateColor(state) { + switch (state) { + case 'running': + return 'success' + case 'completed': + return 'primary' + default: + return 'danger' + } + } +
@@ -86,12 +97,7 @@

Start: {(new Date(job.startTime)).toLocaleString()}
- Duration: {formatDuration(job.duration)} - {#if job.state == 'running'} - running - {:else if job.state != 'completed'} - {job.state} - {/if} + Duration: {formatDuration(job.duration)} {job.state} {#if job.walltime}
Walltime: {formatDuration(job.walltime)} From 84d6b4835360e7435a79df5918b944be73ae9ab2 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Wed, 15 Nov 2023 15:03:58 +0100 Subject: [PATCH 3/7] Fix: default values and new option for time filter --- web/frontend/src/filters/Duration.svelte | 95 +++++++++++++++++++---- web/frontend/src/filters/Filters.svelte | 24 +++++- web/frontend/src/filters/StartTime.svelte | 36 ++++----- 3 files changed, 118 insertions(+), 37 deletions(-) diff --git a/web/frontend/src/filters/Duration.svelte b/web/frontend/src/filters/Duration.svelte index b482b9c4..ca2ce453 100644 --- a/web/frontend/src/filters/Duration.svelte +++ b/web/frontend/src/filters/Duration.svelte @@ -1,18 +1,23 @@ (isOpen = !isOpen)}> - Select Start Time + Select Job Duration -

Between

+

Duration more than

+ + +
+ +
+
h
+
+
+ + +
+ +
+
m
+
+
+ +
+
+ +

Duration less than

- +
h
@@ -46,7 +77,28 @@
- + +
+
m
+
+
+ + +
+ +

Duration between

+ + +
+ +
+
h
+
+
+ + +
+
m
@@ -57,7 +109,7 @@
- +
h
@@ -65,7 +117,7 @@
- +
m
@@ -77,19 +129,30 @@ + + dispatch('update', { lessThan, moreThan, from, to }) + }}>Reset Filter diff --git a/web/frontend/src/filters/Filters.svelte b/web/frontend/src/filters/Filters.svelte index 38d7e7a6..49eaed61 100644 --- a/web/frontend/src/filters/Filters.svelte +++ b/web/frontend/src/filters/Filters.svelte @@ -41,7 +41,7 @@ states: filterPresets.states || filterPresets.state ? [filterPresets.state].flat() : allJobStates, startTime: filterPresets.startTime || { from: null, to: null }, tags: filterPresets.tags || [], - duration: filterPresets.duration || { from: null, to: null }, + duration: filterPresets.duration || { lessThan: null, moreThan: null, from: null, to: null }, jobId: filterPresets.jobId || '', arrayJobId: filterPresets.arrayJobId || null, user: filterPresets.user || '', @@ -88,6 +88,10 @@ items.push({ tags: filters.tags }) if (filters.duration.from || filters.duration.to) items.push({ duration: { from: filters.duration.from, to: filters.duration.to } }) + if (filters.duration.lessThan) + items.push({ duration: { from: 0, to: filters.duration.lessThan } }) + if (filters.duration.moreThan) + items.push({ duration: { from: filters.duration.moreThan, to: 604800 } }) // 7 days to include special jobs with long runtimes if (filters.jobId) items.push({ jobId: { [filters.jobIdMatch]: filters.jobId } }) if (filters.arrayJobId != null) @@ -144,6 +148,10 @@ opts.push(`tag=${tag}`) if (filters.duration.from && filters.duration.to) opts.push(`duration=${filters.duration.from}-${filters.duration.to}`) + if (filters.duration.lessThan) + opts.push(`duration=0-${filters.duration.lessThan}`) + if (filters.duration.moreThan) + opts.push(`duration=${filters.duration.moreThan}-604800`) if (filters.numNodes.from && filters.numNodes.to) opts.push(`numNodes=${filters.numNodes.from}-${filters.numNodes.to}`) if (filters.numAccelerators.from && filters.numAccelerators.to) @@ -267,6 +275,18 @@ {/if} + {#if filters.duration.lessThan} + (isDurationOpen = true)}> + Duration less than {Math.floor(filters.duration.lessThan / 3600)}h:{Math.floor(filters.duration.lessThan % 3600 / 60)}m + + {/if} + + {#if filters.duration.moreThan} + (isDurationOpen = true)}> + Duration more than {Math.floor(filters.duration.moreThan / 3600)}h:{Math.floor(filters.duration.moreThan % 3600 / 60)}m + + {/if} + {#if filters.tags.length != 0} (isTagsOpen = true)}> {#each filters.tags as tagId} @@ -325,6 +345,8 @@ update()} /> diff --git a/web/frontend/src/filters/StartTime.svelte b/web/frontend/src/filters/StartTime.svelte index c89851d4..59f85134 100644 --- a/web/frontend/src/filters/StartTime.svelte +++ b/web/frontend/src/filters/StartTime.svelte @@ -1,5 +1,6 @@ @@ -73,7 +69,7 @@ on:click={() => { isOpen = false from = toRFC3339(pendingFrom) - to = toRFC3339(pendingTo, 59) + to = toRFC3339(pendingTo, '59') dispatch('update', { from, to }) }}> Close & Apply From 782262b52e070a54cd7963bfc555d93e336c3fa4 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Mon, 27 Nov 2023 10:04:36 +0100 Subject: [PATCH 4/7] add missing package date-fns --- web/frontend/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/web/frontend/package.json b/web/frontend/package.json index 3e774748..725f69a9 100644 --- a/web/frontend/package.json +++ b/web/frontend/package.json @@ -20,6 +20,7 @@ "@rollup/plugin-replace": "^5.0.2", "@urql/svelte": "^4.0.1", "chart.js": "^4.3.3", + "date-fns": "^2.30.0", "graphql": "^16.6.0", "svelte-chartjs": "^3.1.2", "sveltestrap": "^5.11.1", From aac3e7d2f4c458cab73ae8a8fcf933c0b42a9aff Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Wed, 29 Nov 2023 10:42:32 +0100 Subject: [PATCH 5/7] fix: fix scope autoselect on jobview statstable --- web/frontend/src/Job.root.svelte | 8 ++++---- web/frontend/src/StatsTable.svelte | 33 ++++++++++++++++-------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/web/frontend/src/Job.root.svelte b/web/frontend/src/Job.root.svelte index 93c58733..83697267 100644 --- a/web/frontend/src/Job.root.svelte +++ b/web/frontend/src/Job.root.svelte @@ -93,7 +93,9 @@ startFetching( job, [...toFetch], - job.numNodes > 2 ? ["node"] : ["node", "core"] + job.numNodes > 2 + ? ["node"] + : ["node", "socket", "core"] ); } else { // Accels and not on node scope @@ -102,7 +104,7 @@ [...toFetch], job.numNodes > 2 ? ["node", "accelerator"] - : ["node", "accelerator", "core"] + : ["node", "accelerator", "socket", "core"] ); } @@ -390,8 +392,6 @@ bind:this={statsTable} job={$initq.data.job} jobMetrics={$jobMetrics.data.jobMetrics} - accMetrics={accMetrics} - accNodeOnly={accNodeOnly} /> {/key} {/if} diff --git a/web/frontend/src/StatsTable.svelte b/web/frontend/src/StatsTable.svelte index e85e8352..e1d0c022 100644 --- a/web/frontend/src/StatsTable.svelte +++ b/web/frontend/src/StatsTable.svelte @@ -7,8 +7,6 @@ export let job export let jobMetrics - export let accMetrics - export let accNodeOnly const allMetrics = [...new Set(jobMetrics.map(m => m.name))].sort(), scopesForMetric = (metric) => jobMetrics @@ -23,17 +21,23 @@ || getContext('cc-config')['job_view_nodestats_selectedMetrics'] for (let metric of allMetrics) { - // Not Exclusive or Single Node: Get maxScope() - // No Accelerators in Job and not Acc-Metric: Use 'core' - // Accelerator Metric available on accelerator scope: Use 'accelerator' - // Accelerator Metric only on node scope: Fallback to 'node' - selectedScopes[metric] = (job.exclusive != 1 || job.numNodes == 1) ? - (job.numAccs != 0 && accMetrics.includes(metric)) ? - accNodeOnly ? - 'node' - : 'accelerator' - : 'core' - : maxScope(scopesForMetric(metric)) + // Not Exclusive or Multi-Node: get maxScope directly (mostly: node) + // -> Else: Load smallest available granularity as default as per availability + const availableScopes = scopesForMetric(metric) + if (job.exclusive != 1 || job.numNodes == 1) { + if (availableScopes.includes('accelerator')) { + selectedScopes[metric] = 'accelerator' + } else if (availableScopes.includes('core')) { + selectedScopes[metric] = 'core' + } else if (availableScopes.includes('socket')) { + selectedScopes[metric] = 'socket' + } else { + selectedScopes[metric] = 'node' + } + } else { + selectedScopes[metric] = maxScope(availableScopes) + } + sorting[metric] = { min: { dir: 'up', active: false }, avg: { dir: 'up', active: false }, @@ -84,8 +88,7 @@ {metric}