mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-07-26 14:16:07 +02:00
fix legends, add resolution, add statsseries, add simple healthcheck
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
export let subCluster = "";
|
||||
export const ccconfig = null;
|
||||
export let selectedMetrics = [];
|
||||
export let selectedResolution = 0;
|
||||
export let hostnameFilter = "";
|
||||
export let systemUnits = null;
|
||||
export let from = null;
|
||||
@@ -39,7 +40,7 @@
|
||||
const { query: initq } = init();
|
||||
const client = getContextClient();
|
||||
const nodeListQuery = gql`
|
||||
query ($cluster: String!, $subCluster: String!, $nodeFilter: String!, $metrics: [String!], $scopes: [MetricScope!]!, $from: Time!, $to: Time!, $paging: PageRequest!) {
|
||||
query ($cluster: String!, $subCluster: String!, $nodeFilter: String!, $metrics: [String!], $scopes: [MetricScope!]!, $from: Time!, $to: Time!, $paging: PageRequest!, $selectedResolution: Int) {
|
||||
nodeMetricsList(
|
||||
cluster: $cluster
|
||||
subCluster: $subCluster
|
||||
@@ -49,6 +50,7 @@
|
||||
from: $from
|
||||
to: $to
|
||||
page: $paging
|
||||
resolution: $selectedResolution
|
||||
) {
|
||||
items {
|
||||
host
|
||||
@@ -63,12 +65,19 @@
|
||||
prefix
|
||||
}
|
||||
series {
|
||||
id
|
||||
hostname
|
||||
data
|
||||
statistics {
|
||||
min
|
||||
avg
|
||||
max
|
||||
}
|
||||
data
|
||||
}
|
||||
statisticsSeries {
|
||||
min
|
||||
median
|
||||
max
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,15 +95,19 @@
|
||||
cluster: cluster,
|
||||
subCluster: subCluster,
|
||||
nodeFilter: hostnameFilter,
|
||||
scopes: ["core", "accelerator"],
|
||||
scopes: ["core", "socket", "accelerator"],
|
||||
metrics: selectedMetrics,
|
||||
from: from.toISOString(),
|
||||
to: to.toISOString(),
|
||||
paging: paging,
|
||||
selectedResolution: selectedResolution,
|
||||
},
|
||||
requestPolicy: "network-only", // Resolution queries are cached, but how to access them? For now: reload on every change
|
||||
});
|
||||
|
||||
$: matchedNodes = $nodesQuery.data?.nodeMetricsList.totalNodes || 0;
|
||||
$: orderedData = $nodesQuery.data?.nodeMetricsList.items.sort((a, b) => a.host.localeCompare(b.host));
|
||||
|
||||
</script>
|
||||
|
||||
{#if $nodesQuery.error}
|
||||
@@ -135,7 +148,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each $nodesQuery.data.nodeMetricsList.items as nodeData (nodeData.host)}
|
||||
{#each orderedData as nodeData (nodeData.host)}
|
||||
<NodeListRow {nodeData} {cluster} {selectedMetrics}/>
|
||||
{:else}
|
||||
<tr>
|
||||
|
@@ -27,6 +27,7 @@
|
||||
export let cluster;
|
||||
export let subCluster
|
||||
export let hostname;
|
||||
export let dataHealth;
|
||||
|
||||
const client = getContextClient();
|
||||
const paging = { itemsPerPage: 50, page: 1 };
|
||||
@@ -49,6 +50,11 @@
|
||||
}
|
||||
`;
|
||||
|
||||
// Not at least one returned, selected metric: NodeHealth warning
|
||||
const healthWarn = !dataHealth.includes(true);
|
||||
// At least one non-returned selected metric: Metric config error?
|
||||
const metricWarn = dataHealth.includes(false);
|
||||
|
||||
$: nodeJobsData = queryStore({
|
||||
client: client,
|
||||
query: nodeJobsQuery,
|
||||
@@ -78,7 +84,31 @@
|
||||
<Spinner />
|
||||
{:else if $nodeJobsData.data}
|
||||
<p>
|
||||
{#if $nodeJobsData.data.jobs.count > 0}
|
||||
{#if healthWarn}
|
||||
<InputGroup>
|
||||
<InputGroupText>
|
||||
<Icon name="exclamation-circle"/>
|
||||
</InputGroupText>
|
||||
<InputGroupText>
|
||||
Status
|
||||
</InputGroupText>
|
||||
<Button color="danger" disabled>
|
||||
Unhealthy
|
||||
</Button>
|
||||
</InputGroup>
|
||||
{:else if metricWarn}
|
||||
<InputGroup>
|
||||
<InputGroupText>
|
||||
<Icon name="circle-half"/>
|
||||
</InputGroupText>
|
||||
<InputGroupText>
|
||||
Status
|
||||
</InputGroupText>
|
||||
<Button color="warning" disabled>
|
||||
Missing Metric
|
||||
</Button>
|
||||
</InputGroup>
|
||||
{:else if $nodeJobsData.data.jobs.count > 0}
|
||||
<InputGroup>
|
||||
<InputGroupText>
|
||||
<Icon name="circle-fill"/>
|
||||
|
@@ -50,7 +50,7 @@
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<NodeInfo {cluster} subCluster={nodeData.subCluster} hostname={nodeData.host} />
|
||||
<NodeInfo {cluster} subCluster={nodeData.subCluster} hostname={nodeData.host} dataHealth={nodeData?.metrics.map((m) => (m.metric.series.length > 0))}/>
|
||||
</td>
|
||||
{#each sortAndSelectScope(nodeData?.metrics) as metricData (metricData.data.name)}
|
||||
<td>
|
||||
@@ -63,11 +63,14 @@
|
||||
{:else}
|
||||
<!-- "No Data"-Warning included in MetricPlot-Component -->
|
||||
<MetricPlot
|
||||
timestep={metricData.data.metric.timestep}
|
||||
series={metricData.data.metric.series}
|
||||
metric={metricData.data.name}
|
||||
{cluster}
|
||||
subCluster={nodeData.subCluster}
|
||||
metric={metricData.data.name}
|
||||
scope={metricData.data.scope}
|
||||
timestep={metricData.data.metric.timestep}
|
||||
series={metricData.data.metric.series}
|
||||
statisticsSeries={metricData.data?.metric.statisticsSeries}
|
||||
useStatsSeries={!!metricData.data?.metric.statisticsSeries}
|
||||
forNode
|
||||
/>
|
||||
{/if}
|
||||
|
Reference in New Issue
Block a user