mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-07-26 06:06:15 +02:00
Migrate user list and analysis view
This commit is contained in:
@@ -37,14 +37,12 @@
|
||||
import ScatterPlot from "./generic/plots/Scatter.svelte";
|
||||
import RooflineHeatmap from "./generic/plots/RooflineHeatmap.svelte";
|
||||
|
||||
const { query: initq } = init();
|
||||
|
||||
export let filterPresets;
|
||||
/* Svelte 5 Props */
|
||||
let { filterPresets } = $props();
|
||||
|
||||
// By default, look at the jobs of the last 6 hours:
|
||||
if (filterPresets?.startTime == null) {
|
||||
if (filterPresets == null) filterPresets = {};
|
||||
|
||||
let now = new Date(Date.now());
|
||||
let hourAgo = new Date(now);
|
||||
hourAgo.setHours(hourAgo.getHours() - 6);
|
||||
@@ -54,27 +52,12 @@
|
||||
};
|
||||
}
|
||||
|
||||
let cluster;
|
||||
let filterComponent; // see why here: https://stackoverflow.com/questions/58287729/how-can-i-export-a-function-from-a-svelte-component-that-changes-a-value-in-the
|
||||
let jobFilters = [];
|
||||
let rooflineMaxY;
|
||||
let colWidth1, colWidth2;
|
||||
let numBins = 50;
|
||||
let maxY = -1;
|
||||
|
||||
/* Const Init */
|
||||
const { query: initq } = init();
|
||||
const client = getContextClient();
|
||||
const initialized = getContext("initialized");
|
||||
const globalMetrics = getContext("globalMetrics");
|
||||
const ccconfig = getContext("cc-config");
|
||||
|
||||
let metricsInHistograms = ccconfig.analysis_view_histogramMetrics,
|
||||
metricsInScatterplots = ccconfig.analysis_view_scatterPlotMetrics;
|
||||
|
||||
$: metrics = [
|
||||
...new Set([...metricsInHistograms, ...metricsInScatterplots.flat()]),
|
||||
];
|
||||
|
||||
$: clusterName = cluster?.name ? cluster.name : cluster;
|
||||
|
||||
const sortOptions = [
|
||||
{ key: "totalWalltime", label: "Walltime" },
|
||||
{ key: "totalNodeHours", label: "Node Hours" },
|
||||
@@ -86,7 +69,22 @@
|
||||
{ key: "project", label: "Project ID" },
|
||||
];
|
||||
|
||||
let sortSelection =
|
||||
/* Var Init */
|
||||
let availableMetrics = [];
|
||||
let metricUnits = {};
|
||||
let metricScopes = {};
|
||||
let rooflineMaxY;
|
||||
let cluster;
|
||||
let colWidth1, colWidth2;
|
||||
let numBins = 50;
|
||||
let maxY = -1;
|
||||
|
||||
/* State Init */
|
||||
let filterComponent = $state(); // see why here: https://stackoverflow.com/questions/58287729/how-can-i-export-a-function-from-a-svelte-component-that-changes-a-value-in-the
|
||||
let jobFilters = $state([]);
|
||||
let metricsInHistograms = $state(ccconfig.analysis_view_histogramMetrics)
|
||||
let metricsInScatterplots = $state(ccconfig.analysis_view_scatterPlotMetrics)
|
||||
let sortSelection = $state(
|
||||
sortOptions.find(
|
||||
(option) =>
|
||||
option.key ==
|
||||
@@ -94,17 +92,20 @@
|
||||
) ||
|
||||
sortOptions.find(
|
||||
(option) => option.key == ccconfig.analysis_view_selectedTopCategory,
|
||||
);
|
||||
let groupSelection =
|
||||
groupOptions.find(
|
||||
(option) =>
|
||||
option.key ==
|
||||
ccconfig[`analysis_view_selectedTopEntity:${filterPresets.cluster}`],
|
||||
) ||
|
||||
groupOptions.find(
|
||||
(option) => option.key == ccconfig.analysis_view_selectedTopEntity,
|
||||
);
|
||||
)
|
||||
);
|
||||
let groupSelection = $state(
|
||||
groupOptions.find(
|
||||
(option) =>
|
||||
option.key ==
|
||||
ccconfig[`analysis_view_selectedTopEntity:${filterPresets.cluster}`],
|
||||
) ||
|
||||
groupOptions.find(
|
||||
(option) => option.key == ccconfig.analysis_view_selectedTopEntity,
|
||||
)
|
||||
);
|
||||
|
||||
/* Init Function */
|
||||
getContext("on-init")(({ data }) => {
|
||||
if (data != null) {
|
||||
cluster = data.clusters.find((c) => c.name == filterPresets.cluster);
|
||||
@@ -121,120 +122,144 @@
|
||||
}
|
||||
});
|
||||
|
||||
const client = getContextClient();
|
||||
/* Derived Vars */
|
||||
let clusterName = $derived(cluster?.name ? cluster.name : cluster);
|
||||
let metrics = $derived(
|
||||
[...new Set([...metricsInHistograms, ...metricsInScatterplots.flat()])]
|
||||
);
|
||||
|
||||
$: statsQuery = queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query ($jobFilters: [JobFilter!]!) {
|
||||
stats: jobsStatistics(filter: $jobFilters) {
|
||||
totalJobs
|
||||
shortJobs
|
||||
totalWalltime
|
||||
totalNodeHours
|
||||
totalCoreHours
|
||||
totalAccHours
|
||||
histDuration {
|
||||
count
|
||||
value
|
||||
}
|
||||
histNumCores {
|
||||
count
|
||||
value
|
||||
let statsQuery = $derived(
|
||||
queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query ($jobFilters: [JobFilter!]!) {
|
||||
stats: jobsStatistics(filter: $jobFilters) {
|
||||
totalJobs
|
||||
shortJobs
|
||||
totalWalltime
|
||||
totalNodeHours
|
||||
totalCoreHours
|
||||
totalAccHours
|
||||
histDuration {
|
||||
count
|
||||
value
|
||||
}
|
||||
histNumCores {
|
||||
count
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { jobFilters },
|
||||
});
|
||||
`,
|
||||
variables: { jobFilters },
|
||||
})
|
||||
);
|
||||
|
||||
$: topQuery = queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query (
|
||||
$jobFilters: [JobFilter!]!
|
||||
$paging: PageRequest!
|
||||
$sortBy: SortByAggregate!
|
||||
$groupBy: Aggregate!
|
||||
) {
|
||||
topList: jobsStatistics(
|
||||
filter: $jobFilters
|
||||
page: $paging
|
||||
sortBy: $sortBy
|
||||
groupBy: $groupBy
|
||||
let topQuery = $derived(
|
||||
queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query (
|
||||
$jobFilters: [JobFilter!]!
|
||||
$paging: PageRequest!
|
||||
$sortBy: SortByAggregate!
|
||||
$groupBy: Aggregate!
|
||||
) {
|
||||
id
|
||||
name
|
||||
totalWalltime
|
||||
totalNodeHours
|
||||
totalCoreHours
|
||||
totalAccHours
|
||||
topList: jobsStatistics(
|
||||
filter: $jobFilters
|
||||
page: $paging
|
||||
sortBy: $sortBy
|
||||
groupBy: $groupBy
|
||||
) {
|
||||
id
|
||||
name
|
||||
totalWalltime
|
||||
totalNodeHours
|
||||
totalCoreHours
|
||||
totalAccHours
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
jobFilters,
|
||||
paging: { itemsPerPage: 10, page: 1 },
|
||||
sortBy: sortSelection.key.toUpperCase(),
|
||||
groupBy: groupSelection.key.toUpperCase(),
|
||||
},
|
||||
});
|
||||
`,
|
||||
variables: {
|
||||
jobFilters,
|
||||
paging: { itemsPerPage: 10, page: 1 },
|
||||
sortBy: sortSelection.key.toUpperCase(),
|
||||
groupBy: groupSelection.key.toUpperCase(),
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// Note: Different footprints than those saved in DB per Job -> Caused by Legacy Naming
|
||||
$: footprintsQuery = queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query ($jobFilters: [JobFilter!]!, $metrics: [String!]!) {
|
||||
footprints: jobsFootprints(filter: $jobFilters, metrics: $metrics) {
|
||||
timeWeights {
|
||||
nodeHours
|
||||
accHours
|
||||
coreHours
|
||||
}
|
||||
metrics {
|
||||
metric
|
||||
data
|
||||
let footprintsQuery = $derived(
|
||||
queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query ($jobFilters: [JobFilter!]!, $metrics: [String!]!) {
|
||||
footprints: jobsFootprints(filter: $jobFilters, metrics: $metrics) {
|
||||
timeWeights {
|
||||
nodeHours
|
||||
accHours
|
||||
coreHours
|
||||
}
|
||||
metrics {
|
||||
metric
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { jobFilters, metrics },
|
||||
});
|
||||
|
||||
$: rooflineQuery = queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query (
|
||||
$jobFilters: [JobFilter!]!
|
||||
$rows: Int!
|
||||
$cols: Int!
|
||||
$minX: Float!
|
||||
$minY: Float!
|
||||
$maxX: Float!
|
||||
$maxY: Float!
|
||||
) {
|
||||
rooflineHeatmap(
|
||||
filter: $jobFilters
|
||||
rows: $rows
|
||||
cols: $cols
|
||||
minX: $minX
|
||||
minY: $minY
|
||||
maxX: $maxX
|
||||
maxY: $maxY
|
||||
)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
jobFilters,
|
||||
rows: 50,
|
||||
cols: 50,
|
||||
minX: 0.01,
|
||||
minY: 1,
|
||||
maxX: 1000,
|
||||
maxY,
|
||||
},
|
||||
`,
|
||||
variables: { jobFilters, metrics },
|
||||
})
|
||||
);
|
||||
|
||||
let rooflineQuery = $derived(
|
||||
queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query (
|
||||
$jobFilters: [JobFilter!]!
|
||||
$rows: Int!
|
||||
$cols: Int!
|
||||
$minX: Float!
|
||||
$minY: Float!
|
||||
$maxX: Float!
|
||||
$maxY: Float!
|
||||
) {
|
||||
rooflineHeatmap(
|
||||
filter: $jobFilters
|
||||
rows: $rows
|
||||
cols: $cols
|
||||
minX: $minX
|
||||
minY: $minY
|
||||
maxX: $maxX
|
||||
maxY: $maxY
|
||||
)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
jobFilters,
|
||||
rows: 50,
|
||||
cols: 50,
|
||||
minX: 0.01,
|
||||
minY: 1,
|
||||
maxX: 1000,
|
||||
maxY,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
/* Reactive Effects */
|
||||
$effect(() => {
|
||||
loadMetrics($initialized)
|
||||
});
|
||||
$effect(() => {
|
||||
updateEntityConfiguration(groupSelection.key);
|
||||
});
|
||||
$effect(() => {
|
||||
updateCategoryConfiguration(sortSelection.key);
|
||||
});
|
||||
|
||||
/* Functions */
|
||||
const updateConfigurationMutation = ({ name, value }) => {
|
||||
return mutationStore({
|
||||
client: client,
|
||||
@@ -287,9 +312,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
let availableMetrics = [];
|
||||
let metricUnits = {};
|
||||
let metricScopes = {};
|
||||
function loadMetrics(isInitialized) {
|
||||
if (!isInitialized) return
|
||||
availableMetrics = [...globalMetrics.filter((gm) => gm?.availability.find((av) => av.cluster == cluster.name))]
|
||||
@@ -299,10 +321,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: loadMetrics($initialized)
|
||||
$: updateEntityConfiguration(groupSelection.key);
|
||||
$: updateCategoryConfiguration(sortSelection.key);
|
||||
|
||||
/* On Mount */
|
||||
onMount(() => filterComponent.updateFilters());
|
||||
</script>
|
||||
|
||||
@@ -329,7 +348,7 @@
|
||||
{filterPresets}
|
||||
disableClusterSelection={true}
|
||||
startTimeQuickSelect={true}
|
||||
on:update-filters={({ detail }) => {
|
||||
applyFilters={(detail) => {
|
||||
jobFilters = detail.filters;
|
||||
}}
|
||||
/>
|
||||
|
Reference in New Issue
Block a user