subcluster in metricSelect, add infobox to systems

- Default: Show Clusters next to Metrics
- New: If Cluster filter activem show subclusters instead (reactive)
- add note to analysis view
- systems view now with info boxes if metric is removed for subcluster
This commit is contained in:
Christoph Kluge 2023-03-31 17:18:16 +02:00
parent 68a839bf1c
commit adc1d94e3f
6 changed files with 77 additions and 22 deletions

View File

@ -269,7 +269,7 @@ func (r *queryResolver) NodeMetrics(ctx context.Context, cluster string, nodes [
for _, scopedMetric := range scopedMetrics {
host.Metrics = append(host.Metrics, &model.JobMetricWithName{
Name: metric,
Scope: schema.MetricScopeNode, // NodeMetrics allow fixed scope?
Scope: schema.MetricScopeNode,
Metric: scopedMetric,
})
}

View File

@ -216,6 +216,7 @@
<Col>
<Card body>
These histograms show the distribution of the averages of all jobs matching the filters. Each job/average is weighted by its node hours.
Note that some metrics could be disabled for specific subclusters as per metriConfig and thus could affect shown average values.
</Card>
<br/>
</Col>
@ -247,6 +248,7 @@
<Col>
<Card body>
Each circle represents one job. The size of a circle is proportional to its node hours. Darker circles mean multiple jobs have the same averages for the respective metrics.
Note that some metrics could be disabled for specific subclusters as per metriConfig and thus could affect shown average values.
</Card>
<br/>
</Col>

View File

@ -15,11 +15,15 @@
export let filterPresets = {}
let filters, jobList, matchedJobs = null
let filters = []
let jobList, matchedJobs = null
let sorting = { field: 'startTime', order: 'DESC' }, isSortingOpen = false, isMetricsSelectionOpen = false
let metrics = filterPresets.cluster
? ccconfig[`plot_list_selectedMetrics:${filterPresets.cluster}`] || ccconfig.plot_list_selectedMetrics
: ccconfig.plot_list_selectedMetrics
let selectedCluster = filterPresets?.cluster ? filterPresets.cluster : null
$: selectedCluster = filters[0]?.cluster ? filters[0].cluster.eq : null
// The filterPresets are handled by the Filters component,
// so we need to wait for it to be ready before we can start a query.
@ -56,7 +60,10 @@
<Filters
filterPresets={filterPresets}
bind:this={filters}
on:update={({ detail }) => jobList.update(detail.filters)} />
on:update={({ detail }) => {
filters = detail.filters
jobList.update(detail.filters)}
} />
</Col>
<Col xs="3" style="margin-left: auto;">
@ -82,7 +89,7 @@
bind:isOpen={isSortingOpen} />
<MetricSelection
cluster={filterPresets.cluster}
bind:cluster={selectedCluster}
configName="plot_list_selectedMetrics"
bind:metrics={metrics}
bind:isOpen={isMetricsSelectionOpen} />

View File

@ -95,7 +95,7 @@
<Modal isOpen={isOpen} toggle={() => (isOpen = !isOpen)}>
<ModalHeader>
Configure columns
Configure columns (Metric availability shown)
</ModalHeader>
<ModalBody>
<ListGroup>
@ -113,9 +113,26 @@
{/if}
{metric}
<span style="float: right;">
{cluster == null ? clusters
{cluster == null ?
clusters // No single cluster specified: List Clusters with Metric
.filter(cluster => cluster.metricConfig.find(m => m.name == metric) != null)
.map(cluster => cluster.name).join(', ') : ''}
.map(cluster => cluster.name).join(', ') :
clusters // Single cluster requested: List Subclusters with do not have metric remove flag
.filter(cluster => cluster.metricConfig.find(m => m.name == metric) != null)
.map(function(cluster) {
let scNames = cluster.subClusters.map(sc => sc.name)
scNames.forEach(function(scName){
let met = cluster.metricConfig.find(m => m.name == metric)
let msc = met.subClusters.find(msc => msc.name == scName)
if (msc != null) {
if (msc.remove == true) {
scNames = scNames.filter(scn => scn != msc.name)
}
}
})
return scNames
})
.join(', ')}
</span>
</li>
{/each}

View File

@ -21,6 +21,7 @@
const clusters = getContext('clusters')
const ccconfig = getContext('cc-config')
const metricConfig = getContext('metrics')
let plotHeight = 300
let hostnameFilter = ''
@ -112,10 +113,22 @@
itemsPerRow={ccconfig.plot_view_plotsPerRow}
items={$nodesQuery.data.nodeMetrics
.filter(h => h.host.includes(hostnameFilter) && h.metrics.some(m => m.name == selectedMetric && m.scope == 'node'))
.map(h => ({ host: h.host, subCluster: h.subCluster, data: h.metrics.find(m => m.name == selectedMetric && m.scope == 'node') }))
.map(function (h) {
let thisConfig = metricConfig(cluster, selectedMetric)
let thisSCIndex = thisConfig.subClusters.findIndex(sc => sc.name == h.subCluster)
// Metric remove == true
if (thisSCIndex >= 0) {
if (thisConfig.subClusters[thisSCIndex].remove == true) {
return { host: h.host, subCluster: h.subCluster, data: null, removed: true }
}
}
// Else
return { host: h.host, subCluster: h.subCluster, data: h.metrics.find(m => m.name == selectedMetric && m.scope == 'node'), removed: false }
})
.sort((a, b) => a.host.localeCompare(b.host))}>
<h4 style="width: 100%; text-align: center;"><a href="/monitoring/node/{cluster}/{item.host}">{item.host} ({item.subCluster})</a></h4>
{#if item.removed == false && item.data != null}
<MetricPlot
width={width}
height={plotHeight}
@ -124,6 +137,11 @@
metric={item.data.name}
cluster={clusters.find(c => c.name == cluster)}
subCluster={item.subCluster} />
{:else if item.removed == true && item.data == null}
<Card body color="info">Metric '{ selectedMetric }' disabled for subcluster '{ item.subCluster }'</Card>
{:else}
<Card body color="warning">Missing Data</Card>
{/if}
</PlotTable>
{/if}
</Col>

View File

@ -18,10 +18,12 @@
export let user
export let filterPresets
let filters, jobList
let filters = []
let jobList
let sorting = { field: 'startTime', order: 'DESC' }, isSortingOpen = false
let metrics = ccconfig.plot_list_selectedMetrics, isMetricsSelectionOpen = false
let w1, w2, histogramHeight = 250
let selectedCluster = filterPresets?.cluster ? filterPresets.cluster : null
const stats = operationStore(`
query($filter: [JobFilter!]!) {
@ -40,6 +42,12 @@
pause: true
})
// filters[filters.findIndex(filter => filter.cluster != null)] ?
// filters[filters.findIndex(filter => filter.cluster != null)].cluster.eq :
// null
// Cluster filter has to be alwas @ first index, above will throw error
$: selectedCluster = filters[0]?.cluster ? filters[0].cluster.eq : null
query(stats)
onMount(() => filters.update())
@ -75,11 +83,12 @@
startTimeQuickSelect={true}
bind:this={filters}
on:update={({ detail }) => {
let filters = [...detail.filters, { user: { eq: user.username } }]
$stats.variables = { filter: filters }
let jobFilters = [...detail.filters, { user: { eq: user.username } }]
$stats.variables = { filter: jobFilters }
$stats.context.pause = false
$stats.reexecute()
jobList.update(filters)
filters = jobFilters
jobList.update(jobFilters)
}} />
</Col>
<Col xs="auto" style="margin-left: auto;">
@ -171,6 +180,8 @@
bind:sorting={sorting}
bind:isOpen={isSortingOpen} />
<MetricSelection configName="plot_list_selectedMetrics"
<MetricSelection
bind:cluster={selectedCluster}
configName="plot_list_selectedMetrics"
bind:metrics={metrics}
bind:isOpen={isMetricsSelectionOpen} />