mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-25 12:59:06 +01:00
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:
parent
68a839bf1c
commit
adc1d94e3f
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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} />
|
||||
|
@ -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}
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
const clusters = getContext('clusters')
|
||||
const ccconfig = getContext('cc-config')
|
||||
const metricConfig = getContext('metrics')
|
||||
|
||||
let plotHeight = 300
|
||||
let hostnameFilter = ''
|
||||
@ -112,18 +113,35 @@
|
||||
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>
|
||||
<MetricPlot
|
||||
width={width}
|
||||
height={plotHeight}
|
||||
timestep={item.data.metric.timestep}
|
||||
series={item.data.metric.series}
|
||||
metric={item.data.name}
|
||||
cluster={clusters.find(c => c.name == cluster)}
|
||||
subCluster={item.subCluster} />
|
||||
<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}
|
||||
timestep={item.data.metric.timestep}
|
||||
series={item.data.metric.series}
|
||||
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>
|
||||
|
@ -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} />
|
Loading…
Reference in New Issue
Block a user