Small migrations and added migration note

This commit is contained in:
Christoph Kluge 2025-06-13 14:39:55 +02:00
parent ad108b285f
commit 27ec445e54
4 changed files with 97 additions and 72 deletions

View File

@ -14,6 +14,17 @@
export let itemsPerRow export let itemsPerRow
export let items export let items
/* Migtation Notes
* Requirements
* - Parent Components must be already Migrated
* - TODO: Job.root.svelte, Node.root.svelte
*
* How-To
* - Define "Plot-Slotcode" as SV5 Snippet with argument "item" in parent (!)
* - Pass new snippet as argument/prop to here
* - @render snippet in items-loop with argument == item
*/
</script> </script>
<Row cols={{ xs: 1, sm: 2, md: 3, lg: itemsPerRow}}> <Row cols={{ xs: 1, sm: 2, md: 3, lg: itemsPerRow}}>

View File

@ -17,11 +17,14 @@
Icon Icon
} from "@sveltestrap/sveltestrap"; } from "@sveltestrap/sveltestrap";
export let cJobs; /* Svelte 5 Props */
export let showLinks = false; let {
export let renderCard = false; cJobs,
export let width = "auto"; showLinks = false,
export let height = "400px"; renderCard = false,
width = "auto",
height = "400px",
} = $props();
</script> </script>
{#if renderCard} {#if renderCard}

View File

@ -23,79 +23,90 @@
} from "@sveltestrap/sveltestrap"; } from "@sveltestrap/sveltestrap";
import { findJobFootprintThresholds } from "../utils.js"; import { findJobFootprintThresholds } from "../utils.js";
export let job; /* Svelte 5 Props */
export let displayTitle = true; let {
export let width = "auto"; job,
export let height = "310px"; displayTitle = true,
width = "auto",
height = "310px",
} = $props();
const footprintData = job?.footprint?.map((jf) => { /* Derived */
const fmc = getContext("getMetricConfig")(job.cluster, job.subCluster, jf.name); const footprintData = $derived(buildFootprint(job?.footprint));
if (fmc) {
// Unit /* Functions */
const unit = (fmc?.unit?.prefix ? fmc.unit.prefix : "") + (fmc?.unit?.base ? fmc.unit.base : "") function buildFootprint(input) {
let result = input?.map((jf) => {
const fmc = getContext("getMetricConfig")(job.cluster, job.subCluster, jf.name);
if (fmc) {
// Unit
const unit = (fmc?.unit?.prefix ? fmc.unit.prefix : "") + (fmc?.unit?.base ? fmc.unit.base : "")
// Threshold / -Differences // Threshold / -Differences
const fmt = findJobFootprintThresholds(job, jf.stat, fmc); const fmt = findJobFootprintThresholds(job, jf.stat, fmc);
// Define basic data -> Value: Use as Provided // Define basic data -> Value: Use as Provided
const fmBase = { const fmBase = {
name: jf.name + ' (' + jf.stat + ')', name: jf.name + ' (' + jf.stat + ')',
avg: jf.value, avg: jf.value,
unit: unit, unit: unit,
max: fmt.peak, max: fmt.peak,
dir: fmc.lowerIsBetter dir: fmc.lowerIsBetter
};
if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "alert")) {
return {
...fmBase,
color: "danger",
message: `Footprint value way ${fmc.lowerIsBetter ? "above" : "below"} expected normal threshold.`,
impact: 3
}; };
} else if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "caution")) {
if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "alert")) {
return {
...fmBase,
color: "danger",
message: `Footprint value way ${fmc.lowerIsBetter ? "above" : "below"} expected normal threshold.`,
impact: 3
};
} else if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "caution")) {
return {
...fmBase,
color: "warning",
message: `Footprint value ${fmc.lowerIsBetter ? "above" : "below"} expected normal threshold.`,
impact: 2,
};
} else if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "normal")) {
return {
...fmBase,
color: "success",
message: "Footprint value within expected thresholds.",
impact: 1,
};
} else if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "peak")) {
return {
...fmBase,
color: "info",
message:
"Footprint value above expected normal threshold: Check for artifacts recommended.",
impact: 0,
};
} else {
return {
...fmBase,
color: "secondary",
message:
"Footprint value above expected peak threshold: Check for artifacts!",
impact: -1,
};
}
} else { // No matching metric config: display as single value
return { return {
...fmBase, name: jf.name + ' (' + jf.stat + ')',
color: "warning", avg: jf.value,
message: `Footprint value ${fmc.lowerIsBetter ? "above" : "below"} expected normal threshold.`,
impact: 2,
};
} else if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "normal")) {
return {
...fmBase,
color: "success",
message: "Footprint value within expected thresholds.",
impact: 1,
};
} else if (evalFootprint(jf.value, fmt, fmc.lowerIsBetter, "peak")) {
return {
...fmBase,
color: "info",
message: message:
"Footprint value above expected normal threshold: Check for artifacts recommended.", `No config for metric ${jf.name} found.`,
impact: 0, impact: 4,
};
} else {
return {
...fmBase,
color: "secondary",
message:
"Footprint value above expected peak threshold: Check for artifacts!",
impact: -1,
}; };
} }
} else { // No matching metric config: display as single value }).sort(function (a, b) { // Sort by impact value primarily, within impact sort name alphabetically
return { return a.impact - b.impact || ((a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));
name: jf.name + ' (' + jf.stat + ')', });;
avg: jf.value,
message: return result;
`No config for metric ${jf.name} found.`, };
impact: 4,
};
}
}).sort(function (a, b) { // Sort by impact value primarily, within impact sort name alphabetically
return a.impact - b.impact || ((a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));
});;
function evalFootprint(value, thresholds, lowerIsBetter, level) { function evalFootprint(value, thresholds, lowerIsBetter, level) {
// Handle Metrics in which less value is better // Handle Metrics in which less value is better
@ -176,7 +187,7 @@
>{fpd.message}</Tooltip >{fpd.message}</Tooltip
> >
</div> </div>
<Row cols={12} class="{(footprintData.length == (index + 1)) ? 'mb-0' : 'mb-2'}"> <Row cols={12} class={(footprintData.length == (index + 1)) ? 'mb-0' : 'mb-2'}>
{#if fpd.dir} {#if fpd.dir}
<Col xs="1"> <Col xs="1">
<Icon name="caret-left-fill" /> <Icon name="caret-left-fill" />

View File

@ -306,7 +306,7 @@
{#if data && data[0].length > 0} {#if data && data[0].length > 0}
<div bind:this={plotWrapper} bind:clientWidth={width} <div bind:this={plotWrapper} bind:clientWidth={width}
style="background-color: rgba(255, 255, 255, 1.0);" class="rounded" style="background-color: rgba(255, 255, 255, 1.0);" class="rounded"
/> ></div>
{:else} {:else}
<Card body color="warning" class="mx-4 my-2" <Card body color="warning" class="mx-4 my-2"
>Cannot render plot: No series data returned for <code>{metric?metric:'job resources'}</code></Card >Cannot render plot: No series data returned for <code>{metric?metric:'job resources'}</code></Card