mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-01-24 02:19:05 +01:00
include feedback on nodeListView
- display names of users and projects - stacked metricPlot for statsSeries
This commit is contained in:
parent
5c2c493c56
commit
d0580592be
@ -423,8 +423,8 @@ func (r *queryResolver) RooflineHeatmap(ctx context.Context, filter []*model.Job
|
|||||||
// NodeMetrics is the resolver for the nodeMetrics field.
|
// NodeMetrics is the resolver for the nodeMetrics field.
|
||||||
func (r *queryResolver) NodeMetrics(ctx context.Context, cluster string, nodes []string, scopes []schema.MetricScope, metrics []string, from time.Time, to time.Time) ([]*model.NodeMetrics, error) {
|
func (r *queryResolver) NodeMetrics(ctx context.Context, cluster string, nodes []string, scopes []schema.MetricScope, metrics []string, from time.Time, to time.Time) ([]*model.NodeMetrics, error) {
|
||||||
user := repository.GetUserFromContext(ctx)
|
user := repository.GetUserFromContext(ctx)
|
||||||
if user != nil && !user.HasRole(schema.RoleAdmin) {
|
if user != nil && !user.HasAnyRole([]schema.Role{schema.RoleAdmin, schema.RoleSupport}) {
|
||||||
return nil, errors.New("you need to be an administrator for this query")
|
return nil, errors.New("you need to be administrator or support staff for this query")
|
||||||
}
|
}
|
||||||
|
|
||||||
if metrics == nil {
|
if metrics == nil {
|
||||||
@ -479,8 +479,8 @@ func (r *queryResolver) NodeMetricsList(ctx context.Context, cluster string, sub
|
|||||||
}
|
}
|
||||||
|
|
||||||
user := repository.GetUserFromContext(ctx)
|
user := repository.GetUserFromContext(ctx)
|
||||||
if user != nil && !user.HasRole(schema.RoleAdmin) {
|
if user != nil && !user.HasAnyRole([]schema.Role{schema.RoleAdmin, schema.RoleSupport}) {
|
||||||
return nil, errors.New("you need to be an administrator for this query")
|
return nil, errors.New("you need to be administrator or support staff for this query")
|
||||||
}
|
}
|
||||||
|
|
||||||
if metrics == nil {
|
if metrics == nil {
|
||||||
|
@ -287,11 +287,11 @@ func LoadNodeListData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: New StatsSeries will always be calculated as 'min/median/max'
|
// NOTE: New StatsSeries will always be calculated as 'min/median/max'
|
||||||
const maxSeriesSize int = 15
|
const maxSeriesSize int = 8
|
||||||
for _, jd := range data {
|
for _, jd := range data {
|
||||||
for _, scopes := range jd {
|
for _, scopes := range jd {
|
||||||
for _, jm := range scopes {
|
for _, jm := range scopes {
|
||||||
if jm.StatisticsSeries != nil || len(jm.Series) <= maxSeriesSize {
|
if jm.StatisticsSeries != nil || len(jm.Series) < maxSeriesSize {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
jm.AddStatisticsSeries()
|
jm.AddStatisticsSeries()
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Nodes",
|
title: "Nodes",
|
||||||
requiredRole: roles.admin,
|
requiredRole: roles.support,
|
||||||
href: "/monitoring/systems/",
|
href: "/monitoring/systems/",
|
||||||
icon: "hdd-rack",
|
icon: "hdd-rack",
|
||||||
perCluster: true,
|
perCluster: true,
|
||||||
@ -102,19 +102,19 @@
|
|||||||
menu: "Info",
|
menu: "Info",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Status",
|
title: "Analysis",
|
||||||
requiredRole: roles.admin,
|
requiredRole: roles.support,
|
||||||
href: "/monitoring/status/",
|
href: "/monitoring/analysis/",
|
||||||
icon: "clipboard-data",
|
icon: "graph-up",
|
||||||
perCluster: true,
|
perCluster: true,
|
||||||
listOptions: false,
|
listOptions: false,
|
||||||
menu: "Info",
|
menu: "Info",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Analysis",
|
title: "Status",
|
||||||
requiredRole: roles.support,
|
requiredRole: roles.admin,
|
||||||
href: "/monitoring/analysis/",
|
href: "/monitoring/status/",
|
||||||
icon: "graph-up",
|
icon: "clipboard-data",
|
||||||
perCluster: true,
|
perCluster: true,
|
||||||
listOptions: false,
|
listOptions: false,
|
||||||
menu: "Info",
|
menu: "Info",
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
- `height Number?`: The plot height [Default: 300]
|
- `height Number?`: The plot height [Default: 300]
|
||||||
- `timestep Number`: The timestep used for X-axis rendering
|
- `timestep Number`: The timestep used for X-axis rendering
|
||||||
- `series [GraphQL.Series]`: The metric data object
|
- `series [GraphQL.Series]`: The metric data object
|
||||||
- `useStatsSeries Bool?`: If this plot uses the statistics Min/Max/Median representation; automatically set to according bool [Default: null]
|
- `useStatsSeries Bool?`: If this plot uses the statistics Min/Max/Median representation; automatically set to according bool [Default: false]
|
||||||
- `statisticsSeries [GraphQL.StatisticsSeries]?`: Min/Max/Median representation of metric data [Default: null]
|
- `statisticsSeries [GraphQL.StatisticsSeries]?`: Min/Max/Median representation of metric data [Default: null]
|
||||||
- `cluster String`: Cluster name of the parent job / data
|
- `cluster String`: Cluster name of the parent job / data
|
||||||
- `subCluster String`: Name of the subCluster of the parent job
|
- `subCluster String`: Name of the subCluster of the parent job
|
||||||
@ -128,7 +128,7 @@
|
|||||||
export let height = 300;
|
export let height = 300;
|
||||||
export let timestep;
|
export let timestep;
|
||||||
export let series;
|
export let series;
|
||||||
export let useStatsSeries = null;
|
export let useStatsSeries = false;
|
||||||
export let statisticsSeries = null;
|
export let statisticsSeries = null;
|
||||||
export let cluster = "";
|
export let cluster = "";
|
||||||
export let subCluster;
|
export let subCluster;
|
||||||
@ -139,10 +139,9 @@
|
|||||||
export let zoomState = null;
|
export let zoomState = null;
|
||||||
export let thresholdState = null;
|
export let thresholdState = null;
|
||||||
|
|
||||||
if (useStatsSeries == null) useStatsSeries = statisticsSeries != null;
|
if (!useStatsSeries && statisticsSeries != null) useStatsSeries = true;
|
||||||
if (useStatsSeries == false && series == null) useStatsSeries = true;
|
|
||||||
|
|
||||||
const usesMeanStatsSeries = (useStatsSeries?.mean && statisticsSeries.mean.length != 0)
|
const usesMeanStatsSeries = (statisticsSeries?.mean && statisticsSeries.mean.length != 0)
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const subClusterTopology = getContext("getHardwareTopology")(cluster, subCluster);
|
const subClusterTopology = getContext("getHardwareTopology")(cluster, subCluster);
|
||||||
const metricConfig = getContext("getMetricConfig")(cluster, subCluster, metric);
|
const metricConfig = getContext("getMetricConfig")(cluster, subCluster, metric);
|
||||||
@ -205,11 +204,10 @@
|
|||||||
|
|
||||||
// conditional hide series color markers:
|
// conditional hide series color markers:
|
||||||
if (
|
if (
|
||||||
useStatsSeries === true || // Min/Max/Median Self-Explanatory
|
useStatsSeries || // Min/Max/Median Self-Explanatory
|
||||||
dataSize === 1 || // Only one Y-Dataseries
|
dataSize === 1 || // Only one Y-Dataseries
|
||||||
dataSize > 6
|
dataSize > 8 // More than 8 Y-Dataseries
|
||||||
) {
|
) {
|
||||||
// More than 6 Y-Dataseries
|
|
||||||
const idents = legendEl.querySelectorAll(".u-marker");
|
const idents = legendEl.querySelectorAll(".u-marker");
|
||||||
for (let i = 0; i < idents.length; i++)
|
for (let i = 0; i < idents.length; i++)
|
||||||
idents[i].style.display = "none";
|
idents[i].style.display = "none";
|
||||||
@ -240,7 +238,7 @@
|
|||||||
"translate(" + (left - width - 15) + "px, " + (top + 15) + "px)";
|
"translate(" + (left - width - 15) + "px, " + (top + 15) + "px)";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataSize <= 12 || useStatsSeries === true) {
|
if (dataSize <= 12 || useStatsSeries) {
|
||||||
return {
|
return {
|
||||||
hooks: {
|
hooks: {
|
||||||
init: init,
|
init: init,
|
||||||
@ -432,13 +430,13 @@
|
|||||||
u.ctx.save();
|
u.ctx.save();
|
||||||
u.ctx.textAlign = "start"; // 'end'
|
u.ctx.textAlign = "start"; // 'end'
|
||||||
u.ctx.fillStyle = "black";
|
u.ctx.fillStyle = "black";
|
||||||
u.ctx.fillText(textl, u.bbox.left + 10, u.bbox.top + 10);
|
u.ctx.fillText(textl, u.bbox.left + 10, u.bbox.top + (forNode ? 0 : 10));
|
||||||
u.ctx.textAlign = "end";
|
u.ctx.textAlign = "end";
|
||||||
u.ctx.fillStyle = "black";
|
u.ctx.fillStyle = "black";
|
||||||
u.ctx.fillText(
|
u.ctx.fillText(
|
||||||
textr,
|
textr,
|
||||||
u.bbox.left + u.bbox.width - 10,
|
u.bbox.left + u.bbox.width - 10,
|
||||||
u.bbox.top + 10,
|
u.bbox.top + (forNode ? 0 : 10),
|
||||||
);
|
);
|
||||||
// u.ctx.fillText(text, u.bbox.left + u.bbox.width - 10, u.bbox.top + u.bbox.height - 10) // Recipe for bottom right
|
// u.ctx.fillText(text, u.bbox.left + u.bbox.width - 10, u.bbox.top + u.bbox.height - 10) // Recipe for bottom right
|
||||||
|
|
||||||
@ -496,10 +494,12 @@
|
|||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
// Display legend until max 12 Y-dataseries
|
// Display legend until max 12 Y-dataseries
|
||||||
show: series.length <= 12 || useStatsSeries === true ? true : false,
|
show: series.length <= 12 || useStatsSeries,
|
||||||
live: series.length <= 12 || useStatsSeries === true ? true : false,
|
live: series.length <= 12 || useStatsSeries,
|
||||||
},
|
},
|
||||||
cursor: { drag: { x: true, y: true } },
|
cursor: {
|
||||||
|
drag: { x: true, y: true },
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// RENDER HANDLING
|
// RENDER HANDLING
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
$paging: PageRequest!
|
$paging: PageRequest!
|
||||||
) {
|
) {
|
||||||
jobs(filter: $filter, order: $sorting, page: $paging) {
|
jobs(filter: $filter, order: $sorting, page: $paging) {
|
||||||
|
items {
|
||||||
|
user
|
||||||
|
project
|
||||||
|
exclusive
|
||||||
|
}
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,6 +66,13 @@
|
|||||||
variables: { paging, sorting, filter },
|
variables: { paging, sorting, filter },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let userList;
|
||||||
|
let projectList;
|
||||||
|
$: if ($nodeJobsData?.data) {
|
||||||
|
userList = Array.from(new Set($nodeJobsData.data.jobs.items.map((j) => j.user))).sort((a, b) => a.localeCompare(b));
|
||||||
|
projectList = Array.from(new Set($nodeJobsData.data.jobs.items.map((j) => j.project))).sort((a, b) => a.localeCompare(b));
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Card class="pb-3">
|
<Card class="pb-3">
|
||||||
@ -83,7 +95,6 @@
|
|||||||
{#if $nodeJobsData.fetching}
|
{#if $nodeJobsData.fetching}
|
||||||
<Spinner />
|
<Spinner />
|
||||||
{:else if $nodeJobsData.data}
|
{:else if $nodeJobsData.data}
|
||||||
<p>
|
|
||||||
{#if healthWarn}
|
{#if healthWarn}
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
@ -99,7 +110,7 @@
|
|||||||
{:else if metricWarn}
|
{:else if metricWarn}
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
<Icon name="circle-half"/>
|
<Icon name="info-circle"/>
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
Status
|
Status
|
||||||
@ -108,7 +119,7 @@
|
|||||||
Missing Metric
|
Missing Metric
|
||||||
</Button>
|
</Button>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
{:else if $nodeJobsData.data.jobs.count > 0}
|
{:else if $nodeJobsData.data.jobs.count == 1 && $nodeJobsData.data.jobs.items[0].exclusive}
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
<Icon name="circle-fill"/>
|
<Icon name="circle-fill"/>
|
||||||
@ -117,7 +128,19 @@
|
|||||||
Status
|
Status
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Button color="success" disabled>
|
<Button color="success" disabled>
|
||||||
Allocated
|
Exclusive
|
||||||
|
</Button>
|
||||||
|
</InputGroup>
|
||||||
|
{:else if $nodeJobsData.data.jobs.count >= 1 && !$nodeJobsData.data.jobs.items[0].exclusive}
|
||||||
|
<InputGroup>
|
||||||
|
<InputGroupText>
|
||||||
|
<Icon name="circle-half"/>
|
||||||
|
</InputGroupText>
|
||||||
|
<InputGroupText>
|
||||||
|
Status
|
||||||
|
</InputGroupText>
|
||||||
|
<Button color="success" disabled>
|
||||||
|
Shared
|
||||||
</Button>
|
</Button>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
{:else}
|
{:else}
|
||||||
@ -133,63 +156,63 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
{/if}
|
{/if}
|
||||||
</p>
|
<hr class="my-3"/>
|
||||||
<hr class="mt-0 mb-3"/>
|
<!-- JOBS -->
|
||||||
<p>
|
<InputGroup size="sm" class="justify-content-between mb-3">
|
||||||
{#if $nodeJobsData.data.jobs.count > 0}
|
|
||||||
<InputGroup size="sm" class="justify-content-between">
|
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
<Icon name="activity"/>
|
<Icon name="activity"/>
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<InputGroupText>
|
<InputGroupText class="justify-content-center" style="width: 4.4rem;">
|
||||||
Activity
|
Activity
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Input class="flex-grow-1" style="background-color: white;" type="text" value="{$nodeJobsData.data.jobs.count} Jobs" disabled />
|
<Input class="flex-grow-1" style="background-color: white;" type="text" value="{$nodeJobsData?.data?.jobs?.count || 0} Job{($nodeJobsData?.data?.jobs?.count == 1) ? '': 's'}" disabled />
|
||||||
<a title="Show jobs running on this node" href="/monitoring/jobs/?cluster={cluster}&state=running&node={hostname}" target="_blank" class="btn btn-outline-primary" role="button" aria-disabled="true" >
|
<a title="Show jobs running on this node" href="/monitoring/jobs/?cluster={cluster}&state=running&node={hostname}" target="_blank" class="btn btn-outline-primary" role="button" aria-disabled="true" >
|
||||||
<Icon name="view-list" />
|
<Icon name="view-list" />
|
||||||
List
|
List
|
||||||
</a>
|
</a>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
{:else}
|
<!-- USERS -->
|
||||||
<InputGroup size="sm" class="justify-content-between">
|
<InputGroup size="sm" class="justify-content-between {(userList?.length > 0) ? 'mb-1' : 'mb-3'}">
|
||||||
<InputGroupText>
|
|
||||||
<Icon name="activity" />
|
|
||||||
</InputGroupText>
|
|
||||||
<InputGroupText>
|
|
||||||
Activity
|
|
||||||
</InputGroupText>
|
|
||||||
<Input class="flex-grow-1" type="text" style="background-color: white;" value="No running jobs." disabled />
|
|
||||||
</InputGroup>
|
|
||||||
{/if}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<InputGroup size="sm" class="justify-content-between">
|
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
<Icon name="people"/>
|
<Icon name="people"/>
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<InputGroupText class="flex-fill">
|
<InputGroupText class="justify-content-center" style="width: 4.4rem;">
|
||||||
Show Users
|
Users
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
|
<Input class="flex-grow-1" style="background-color: white;" type="text" value="{userList?.length || 0} User{(userList?.length == 1) ? '': 's'}" disabled />
|
||||||
<a title="Show users active on this node" href="/monitoring/users/?cluster={cluster}&state=running&node={hostname}" target="_blank" class="btn btn-outline-primary" role="button" aria-disabled="true" >
|
<a title="Show users active on this node" href="/monitoring/users/?cluster={cluster}&state=running&node={hostname}" target="_blank" class="btn btn-outline-primary" role="button" aria-disabled="true" >
|
||||||
<Icon name="view-list" />
|
<Icon name="view-list" />
|
||||||
List
|
List
|
||||||
</a>
|
</a>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</p>
|
{#if userList?.length > 0}
|
||||||
<p>
|
<Card class="mb-3">
|
||||||
<InputGroup size="sm" class="justify-content-between">
|
<div class="p-1">
|
||||||
|
{userList.join(", ")}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
{/if}
|
||||||
|
<!-- PROJECTS -->
|
||||||
|
<InputGroup size="sm" class="justify-content-between {(projectList?.length > 0) ? 'mb-1' : 'mb-3'}">
|
||||||
<InputGroupText>
|
<InputGroupText>
|
||||||
<Icon name="journals"/>
|
<Icon name="journals"/>
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<InputGroupText class="flex-fill">
|
<InputGroupText class="justify-content-center" style="width: 4.4rem;">
|
||||||
Show Projects
|
Projects
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
|
<Input class="flex-grow-1" style="background-color: white;" type="text" value="{projectList?.length || 0} Project{(projectList?.length == 1) ? '': 's'}" disabled />
|
||||||
<a title="Show projects active on this node" href="/monitoring/projects/?cluster={cluster}&state=running&node={hostname}" target="_blank" class="btn btn-outline-primary" role="button" aria-disabled="true" >
|
<a title="Show projects active on this node" href="/monitoring/projects/?cluster={cluster}&state=running&node={hostname}" target="_blank" class="btn btn-outline-primary" role="button" aria-disabled="true" >
|
||||||
<Icon name="view-list" />
|
<Icon name="view-list" />
|
||||||
List
|
List
|
||||||
</a>
|
</a>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</p>
|
{#if projectList?.length > 0}
|
||||||
|
<Card>
|
||||||
|
<div class="p-1">
|
||||||
|
{projectList.join(", ")}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -46,13 +46,21 @@
|
|||||||
return scopedNodeMetric;
|
return scopedNodeMetric;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let refinedData;
|
||||||
|
let dataHealth;
|
||||||
|
$: if (nodeData?.metrics) {
|
||||||
|
refinedData = sortAndSelectScope(nodeData?.metrics)
|
||||||
|
// Check data for series, skip disabled
|
||||||
|
dataHealth = refinedData.filter((rd) => rd.disabled === false).map((enabled) => (enabled.data.metric.series.length > 0))
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<NodeInfo {cluster} subCluster={nodeData.subCluster} hostname={nodeData.host} dataHealth={nodeData?.metrics.map((m) => (m.metric.series.length > 0))}/>
|
<NodeInfo {cluster} subCluster={nodeData.subCluster} hostname={nodeData.host} {dataHealth}/>
|
||||||
</td>
|
</td>
|
||||||
{#each sortAndSelectScope(nodeData?.metrics) as metricData (metricData.data.name)}
|
{#each refinedData as metricData (metricData.data.name)}
|
||||||
<td>
|
<td>
|
||||||
{#if metricData?.disabled}
|
{#if metricData?.disabled}
|
||||||
<Card body class="mx-3" color="info"
|
<Card body class="mx-3" color="info"
|
||||||
@ -60,7 +68,7 @@
|
|||||||
>{metricData.data.name}:{nodeData.subCluster}</code
|
>{metricData.data.name}:{nodeData.subCluster}</code
|
||||||
></Card
|
></Card
|
||||||
>
|
>
|
||||||
{:else}
|
{:else if !!metricData.data?.metric.statisticsSeries}
|
||||||
<!-- "No Data"-Warning included in MetricPlot-Component -->
|
<!-- "No Data"-Warning included in MetricPlot-Component -->
|
||||||
<MetricPlot
|
<MetricPlot
|
||||||
{cluster}
|
{cluster}
|
||||||
@ -71,6 +79,29 @@
|
|||||||
series={metricData.data.metric.series}
|
series={metricData.data.metric.series}
|
||||||
statisticsSeries={metricData.data?.metric.statisticsSeries}
|
statisticsSeries={metricData.data?.metric.statisticsSeries}
|
||||||
useStatsSeries={!!metricData.data?.metric.statisticsSeries}
|
useStatsSeries={!!metricData.data?.metric.statisticsSeries}
|
||||||
|
height={175}
|
||||||
|
forNode
|
||||||
|
/>
|
||||||
|
<div class="my-2"/>
|
||||||
|
<MetricPlot
|
||||||
|
{cluster}
|
||||||
|
subCluster={nodeData.subCluster}
|
||||||
|
metric={metricData.data.name}
|
||||||
|
scope={metricData.data.scope}
|
||||||
|
timestep={metricData.data.metric.timestep}
|
||||||
|
series={metricData.data.metric.series}
|
||||||
|
height={175}
|
||||||
|
forNode
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<MetricPlot
|
||||||
|
{cluster}
|
||||||
|
subCluster={nodeData.subCluster}
|
||||||
|
metric={metricData.data.name}
|
||||||
|
scope={metricData.data.scope}
|
||||||
|
timestep={metricData.data.metric.timestep}
|
||||||
|
series={metricData.data.metric.series}
|
||||||
|
height={375}
|
||||||
forNode
|
forNode
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
Loading…
Reference in New Issue
Block a user