diff --git a/web/frontend/src/Job.root.svelte b/web/frontend/src/Job.root.svelte index a393995f..50de27b5 100644 --- a/web/frontend/src/Job.root.svelte +++ b/web/frontend/src/Job.root.svelte @@ -68,12 +68,8 @@ energyFootprint { hardware, metric, value } } `); - const client = getContextClient(); - const ccconfig = getContext("cc-config"); - const showRoofline = !!ccconfig[`jobView_showRoofline`]; - const showStatsTable = !!ccconfig[`jobView_showStatTable`]; - /* Note: Actual metric data queried in Component, only require base infos here -> reduce backend load by requesting just stats */ + const client = getContextClient(); const query = gql` query ($dbid: ID!, $selectedMetrics: [String!]!, $selectedScopes: [MetricScope!]!) { scopedJobStats(id: $dbid, metrics: $selectedMetrics, scopes: $selectedScopes) { @@ -89,25 +85,68 @@ /* State Init */ let plots = $state({}); let isMetricsSelectionOpen = $state(false); - let selectedMetrics = $state([]); - let selectedScopes = $state([]); let totalMetrics = $state(0); - /* Derived */ - const showSummary = $derived((!!ccconfig[`jobView_showFootprint`] || !!ccconfig[`jobView_showPolarPlot`])) + /* Derived Init Return */ + const thisJob = $derived($initq?.data ? $initq.data.job : null); + + /* Derived Settings */ + const globalMetrics = $derived(thisJob ? getContext("globalMetrics") : null); + const clusterInfo = $derived(thisJob ? getContext("clusters") : null); + const ccconfig = $derived(thisJob ? getContext("cc-config") : null); + const showRoofline = $derived(ccconfig ? !!ccconfig[`jobView_showRoofline`] : false); + const showStatsTable = $derived(ccconfig ? !!ccconfig[`jobView_showStatTable`] : false); + const showSummary = $derived(ccconfig ? (!!ccconfig[`jobView_showFootprint`] || !!ccconfig[`jobView_showPolarPlot`]) : false) + + /* Derived Var Preprocessing*/ + let selectedMetrics = $derived.by(() => { + if(thisJob && ccconfig) { + if (thisJob.cluster) { + if (thisJob.subCluster) { + return ccconfig[`metricConfig_jobViewPlotMetrics:${thisJob.cluster}:${thisJob.subCluster}`] || + ccconfig[`metricConfig_jobViewPlotMetrics:${thisJob.cluster}`] || + ccconfig.metricConfig_jobViewPlotMetrics + } + return ccconfig[`metricConfig_jobViewPlotMetrics:${thisJob.cluster}`] || + ccconfig.metricConfig_jobViewPlotMetrics + } + return ccconfig.metricConfig_jobViewPlotMetrics + } + return []; + }); + + let selectedScopes = $derived.by(() => { + const pendingScopes = ["node"] + if (thisJob) { + const accScopeDefault = [...selectedMetrics].some(function (m) { + const thisCluster = clusterInfo.find((c) => c.name == thisJob.cluster); + const subCluster = thisCluster.subClusters.find((sc) => sc.name == thisJob.subCluster); + return subCluster.metricConfig.find((smc) => smc.name == m)?.scope === "accelerator"; + }); + + + if (accScopeDefault) pendingScopes.push("accelerator") + if (thisJob.numNodes === 1) { + pendingScopes.push("socket") + pendingScopes.push("core") + } + } + return[...new Set(pendingScopes)]; + }); + + /* Derived Query and Postprocessing*/ const jobMetrics = $derived(queryStore({ client: client, query: query, variables: { dbid, selectedMetrics, selectedScopes }, }) ); - + const missingMetrics = $derived.by(() => { - if ($initq?.data && $jobMetrics?.data) { - let job = $initq.data.job; + if (thisJob && $jobMetrics?.data) { let metrics = $jobMetrics.data.scopedJobStats; - let metricNames = $initq.data.globalMetrics.reduce((names, gm) => { - if (gm.availability.find((av) => av.cluster === job.cluster)) { + let metricNames = globalMetrics.reduce((names, gm) => { + if (gm.availability.find((av) => av.cluster === thisJob.cluster)) { names.push(gm.name); } return names; @@ -118,9 +157,10 @@ !metrics.some((jm) => jm.name == metric) && selectedMetrics.includes(metric) && !checkMetricDisabled( + globalMetrics, metric, - $initq.data.job.cluster, - $initq.data.job.subCluster, + thisJob.cluster, + thisJob.subCluster, ), ); } else { @@ -129,17 +169,16 @@ }); const missingHosts = $derived.by(() => { - if ($initq?.data && $jobMetrics?.data) { - let job = $initq.data.job; + if (thisJob && $jobMetrics?.data) { let metrics = $jobMetrics.data.scopedJobStats; - let metricNames = $initq.data.globalMetrics.reduce((names, gm) => { - if (gm.availability.find((av) => av.cluster === job.cluster)) { + let metricNames = globalMetrics.reduce((names, gm) => { + if (gm.availability.find((av) => av.cluster === thisJob.cluster)) { names.push(gm.name); } return names; }, []); - return job.resources + return thisJob.resources .map(({ hostname }) => ({ hostname: hostname, metrics: metricNames.filter( @@ -165,51 +204,19 @@ ? "Loading..." : $initq?.error ? "Error" - : `Job ${$initq.data.job.jobId} - ClusterCockpit`; - }); - - /* On Init */ - getContext("on-init")(() => { - let job = $initq.data.job; - if (!job) return; - const pendingMetrics = ( - ccconfig[`metricConfig_jobViewPlotMetrics:${job.cluster}:${job.subCluster}`] || - ccconfig[`metricConfig_jobViewPlotMetrics:${job.cluster}`] - ) || - $initq.data.globalMetrics.reduce((names, gm) => { - if (gm.availability.find((av) => av.cluster === job.cluster && av.subClusters.includes(job.subCluster))) { - names.push(gm.name); - } - return names; - }, []) - - // Select default Scopes to load: Check before if any metric has accelerator scope by default - const accScopeDefault = [...pendingMetrics].some(function (m) { - const cluster = $initq.data.clusters.find((c) => c.name == job.cluster); - const subCluster = cluster.subClusters.find((sc) => sc.name == job.subCluster); - return subCluster.metricConfig.find((smc) => smc.name == m)?.scope === "accelerator"; - }); - - const pendingScopes = ["node"] - if (accScopeDefault) pendingScopes.push("accelerator") - if (job.numNodes === 1) { - pendingScopes.push("socket") - pendingScopes.push("core") - } - - selectedMetrics = [...new Set(pendingMetrics)]; - selectedScopes = [...new Set(pendingScopes)]; + : `Job ${thisJob.jobId} - ClusterCockpit`; }); /* Functions */ - const orderAndMap = (grouped, selectedMetrics) => - selectedMetrics.map((metric) => ({ + const orderAndMap = (grouped, inputMetrics) => + inputMetrics.map((metric) => ({ metric: metric, data: grouped.find((group) => group[0].name == metric), disabled: checkMetricDisabled( + globalMetrics, metric, - $initq.data.job.cluster, - $initq.data.job.subCluster, + thisJob.cluster, + thisJob.subCluster, ), })); @@ -219,34 +226,34 @@ {#if $initq.error} {$initq.error.message} - {:else if $initq?.data} + {:else if thisJob} - {#if $initq.data?.job?.metaData?.message} + {#if thisJob?.metaData?.message} -
Job {$initq.data?.job?.jobId} ({$initq.data?.job?.cluster})
+
Job {thisJob?.jobId} ({thisJob?.cluster})
The following note was added by administrators:
- {@html $initq.data.job.metaData.message} + {@html thisJob.metaData.message}
{/if} - + - + - {#if $initq.data.job.concurrentJobs != null && $initq.data.job.concurrentJobs.items.length != 0} + {#if thisJob.concurrentJobs != null && thisJob.concurrentJobs.items.length != 0} - {$initq.data.job.concurrentJobs.items.length} Concurrent Jobs + {thisJob.concurrentJobs.items.length} Concurrent Jobs - roles.manager)}/> + roles.manager)}/> {/if} @@ -261,9 +268,9 @@ {#if $initq.error} {$initq.error.message} - {:else if $initq?.data} + {:else if thisJob} {#if showSummary} - + {/if} {:else} @@ -274,9 +281,9 @@ {#if $initq.error} {$initq.error.message} - {:else if $initq?.data} + {:else if thisJob} {#if showRoofline} - + {/if} {:else} @@ -285,10 +292,10 @@ -{#if $initq?.data && $initq.data.job.energyFootprint.length != 0} +{#if thisJob && thisJob?.energyFootprint?.length != 0} - + {/if} @@ -297,7 +304,7 @@ - {#if $initq?.data} + {#if thisJob} {#if job.numNodes > 1 && job.state === "running"} -