mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-07-26 06:06:15 +02:00
Merge branch 'master' into 166_add_scopes_analysis
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
<script>
|
||||
import { init } from './utils.js'
|
||||
import { init, convert2uplot } from './utils.js'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { queryStore, gql, getContextClient } from '@urql/svelte'
|
||||
import { Row, Col, Spinner, Card, Table } from 'sveltestrap'
|
||||
import { Row, Col, Spinner, Card, Table, Icon } from 'sveltestrap'
|
||||
import Filters from './filters/Filters.svelte'
|
||||
import PlotSelection from './PlotSelection.svelte'
|
||||
import Histogram, { binsFromFootprint } from './plots/Histogram.svelte'
|
||||
import Histogram from './plots/Histogram.svelte'
|
||||
import Pie, { colors } from './plots/Pie.svelte'
|
||||
import { binsFromFootprint } from './utils.js'
|
||||
import ScatterPlot from './plots/Scatter.svelte'
|
||||
import PlotTable from './PlotTable.svelte'
|
||||
import Roofline from './plots/Roofline.svelte'
|
||||
@@ -29,7 +31,7 @@
|
||||
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 colWidth;
|
||||
let colWidth1, colWidth2, colWidth3, colWidth4;
|
||||
let numBins = 50;
|
||||
let maxY = -1;
|
||||
const ccconfig = getContext('cc-config')
|
||||
@@ -134,78 +136,104 @@
|
||||
</Col>
|
||||
</Row>
|
||||
{:else if $statsQuery.data}
|
||||
<Row>
|
||||
<div class="col-3" bind:clientWidth={colWidth}>
|
||||
<div style="height: 40%">
|
||||
<Table>
|
||||
<tr>
|
||||
<th scope="col">Total Jobs</th>
|
||||
<td>{$statsQuery.data.stats[0].totalJobs}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Short Jobs</th>
|
||||
<td>{$statsQuery.data.stats[0].shortJobs}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Total Walltime</th>
|
||||
<td>{$statsQuery.data.stats[0].totalWalltime}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Total Core Hours</th>
|
||||
<td>{$statsQuery.data.stats[0].totalCoreHours}</td>
|
||||
</tr>
|
||||
</Table>
|
||||
</div>
|
||||
<div style="height: 60%;">
|
||||
{#key $statsQuery.data.topUsers}
|
||||
<h4>Top Users (by node hours)</h4>
|
||||
<Histogram
|
||||
width={colWidth - 25} height={300 * 0.5} small={true}
|
||||
data={$statsQuery.data.topUsers.sort((a, b) => b.count - a.count).map(({ count }, idx) => ({ count, value: idx }))}
|
||||
label={(x) => x < $statsQuery.data.topUsers.length ? $statsQuery.data.topUsers[Math.floor(x)].name : 'No Users'}
|
||||
ylabel="Node Hours [h]"/>
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
{#key $statsQuery.data.stats[0].histDuration}
|
||||
<h4>Duration Distribution</h4>
|
||||
<Histogram
|
||||
width={colWidth - 25}
|
||||
data={$statsQuery.data.stats[0].histDuration}
|
||||
xlabel="Current Runtimes [h]"
|
||||
ylabel="Number of Jobs"/>
|
||||
<Row cols={3} class="mb-4">
|
||||
<Col>
|
||||
<Table>
|
||||
<tr>
|
||||
<th scope="col">Total Jobs</th>
|
||||
<td>{$statsQuery.data.stats[0].totalJobs}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Short Jobs</th>
|
||||
<td>{$statsQuery.data.stats[0].shortJobs}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Total Walltime</th>
|
||||
<td>{$statsQuery.data.stats[0].totalWalltime}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Total Core Hours</th>
|
||||
<td>{$statsQuery.data.stats[0].totalCoreHours}</td>
|
||||
</tr>
|
||||
</Table>
|
||||
</Col>
|
||||
<Col>
|
||||
<div bind:clientWidth={colWidth1}>
|
||||
<h5>Top Users</h5>
|
||||
{#key $statsQuery.data.topUsers}
|
||||
<Pie
|
||||
size={colWidth1}
|
||||
sliceLabel='Hours'
|
||||
quantities={$statsQuery.data.topUsers.sort((a, b) => b.count - a.count).map((tu) => tu.count)}
|
||||
entities={$statsQuery.data.topUsers.sort((a, b) => b.count - a.count).map((tu) => tu.name)}
|
||||
/>
|
||||
{/key}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
{#key $statsQuery.data.stats[0].histNumNodes}
|
||||
<h4>Number of Nodes Distribution</h4>
|
||||
<Histogram
|
||||
width={colWidth - 25}
|
||||
data={$statsQuery.data.stats[0].histNumNodes}
|
||||
xlabel="Allocated Nodes [#]"
|
||||
ylabel="Number of Jobs" />
|
||||
{/key}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
<Table>
|
||||
<tr class="mb-2"><th>Legend</th><th>User Name</th><th>Node Hours</th></tr>
|
||||
{#each $statsQuery.data.topUsers.sort((a, b) => b.count - a.count) as { name, count }, i}
|
||||
<tr>
|
||||
<td><Icon name="circle-fill" style="color: {colors[i]};"/></td>
|
||||
<th scope="col"><a href="/monitoring/user/{name}?cluster={cluster.name}">{name}</a></th>
|
||||
<td>{count}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</Table>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row cols={3} class="mb-2">
|
||||
<Col>
|
||||
{#if $rooflineQuery.fetching}
|
||||
<Spinner />
|
||||
{:else if $rooflineQuery.error}
|
||||
<Card body color="danger">{$rooflineQuery.error.message}</Card>
|
||||
{:else if $rooflineQuery.data && cluster}
|
||||
<div bind:clientWidth={colWidth2}>
|
||||
{#key $rooflineQuery.data}
|
||||
<Roofline
|
||||
width={colWidth - 25}
|
||||
width={colWidth2} height={300}
|
||||
tiles={$rooflineQuery.data.rooflineHeatmap}
|
||||
cluster={cluster.subClusters.length == 1 ? cluster.subClusters[0] : null}
|
||||
maxY={rooflineMaxY} />
|
||||
{/key}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
<div bind:clientWidth={colWidth3}>
|
||||
{#key $statsQuery.data.stats[0].histDuration}
|
||||
<Histogram
|
||||
width={colWidth3} height={300}
|
||||
data={convert2uplot($statsQuery.data.stats[0].histDuration)}
|
||||
title="Duration Distribution"
|
||||
xlabel="Current Runtimes"
|
||||
xunit="Hours"
|
||||
ylabel="Number of Jobs"
|
||||
yunit="Jobs"/>
|
||||
{/key}
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
<div bind:clientWidth={colWidth4}>
|
||||
{#key $statsQuery.data.stats[0].histNumNodes}
|
||||
<Histogram
|
||||
width={colWidth4} height={300}
|
||||
data={convert2uplot($statsQuery.data.stats[0].histNumNodes)}
|
||||
title="Number of Nodes Distribution"
|
||||
xlabel="Allocated Nodes"
|
||||
xunit="Nodes"
|
||||
ylabel="Number of Jobs"
|
||||
yunit="Jobs"/>
|
||||
{/key}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
{/if}
|
||||
|
||||
<br/>
|
||||
<hr class="my-6"/>
|
||||
|
||||
{#if $footprintsQuery.error}
|
||||
<Row>
|
||||
<Col>
|
||||
@@ -233,15 +261,16 @@
|
||||
$footprintsQuery.data.footprints.metrics.find(f => f.metric == metric).data, numBins) }))}
|
||||
itemsPerRow={ccconfig.plot_view_plotsPerRow}>
|
||||
|
||||
<h4>Average Distribution of '{item.metric}'</h4>
|
||||
<Histogram
|
||||
data={convert2uplot(item.bins)}
|
||||
width={width} height={250}
|
||||
min={item.min} max={item.max}
|
||||
data={item.bins}
|
||||
label={item.label}
|
||||
xlabel={`${item.metric} Average [${(metricConfig(cluster.name, item.metric)?.unit?.prefix ? metricConfig(cluster.name, item.metric)?.unit?.prefix : '') +
|
||||
title="Average Distribution of '{item.metric}'"
|
||||
xlabel={`${item.metric} average [${(metricConfig(cluster.name, item.metric)?.unit?.prefix ? metricConfig(cluster.name, item.metric)?.unit?.prefix : '') +
|
||||
(metricConfig(cluster.name, item.metric)?.unit?.base ? metricConfig(cluster.name, item.metric)?.unit?.base : '')}]`}
|
||||
ylabel="Node Hours [h]" />
|
||||
xunit={`${(metricConfig(cluster.name, item.metric)?.unit?.prefix ? metricConfig(cluster.name, item.metric)?.unit?.prefix : '') +
|
||||
(metricConfig(cluster.name, item.metric)?.unit?.base ? metricConfig(cluster.name, item.metric)?.unit?.base : '')}`}
|
||||
ylabel="Node Hours"
|
||||
yunit="Hours"/>
|
||||
</PlotTable>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -260,6 +289,7 @@
|
||||
<PlotTable
|
||||
let:item
|
||||
let:width
|
||||
renderFor="analysis"
|
||||
items={metricsInScatterplots.map(([m1, m2]) => ({
|
||||
m1, f1: $footprintsQuery.data.footprints.metrics.find(f => f.metric == m1).data,
|
||||
m2, f2: $footprintsQuery.data.footprints.metrics.find(f => f.metric == m2).data }))}
|
||||
@@ -278,7 +308,7 @@
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
h4 {
|
||||
h5 {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user