cc-backend/web/frontend/src/Node.root.svelte

229 lines
7.1 KiB
Svelte
Raw Normal View History

2022-06-22 11:20:57 +02:00
<script>
2023-07-03 09:01:28 +02:00
import { init, checkMetricDisabled } from "./utils.js";
import {
Row,
Col,
InputGroup,
InputGroupText,
Icon,
Spinner,
Card,
} from "sveltestrap";
import { queryStore, gql, getContextClient } from "@urql/svelte";
import TimeSelection from "./filters/TimeSelection.svelte";
import PlotTable from "./PlotTable.svelte";
import MetricPlot from "./plots/MetricPlot.svelte";
import { getContext } from "svelte";
2022-06-22 11:20:57 +02:00
2023-07-03 09:01:28 +02:00
export let cluster;
export let hostname;
export let from = null;
export let to = null;
2022-06-22 11:20:57 +02:00
2023-07-03 09:01:28 +02:00
const { query: initq } = init();
2022-06-22 11:20:57 +02:00
if (from == null || to == null) {
2023-07-03 09:01:28 +02:00
to = new Date(Date.now());
from = new Date(to.getTime());
from.setMinutes(from.getMinutes() - 30);
2022-06-22 11:20:57 +02:00
}
2023-07-03 09:01:28 +02:00
const ccconfig = getContext("cc-config");
const clusters = getContext("clusters");
2023-05-10 16:35:21 +02:00
const client = getContextClient();
2023-07-03 09:01:28 +02:00
const nodeMetricsQuery = gql`
query ($cluster: String!, $nodes: [String!], $from: Time!, $to: Time!) {
nodeMetrics(
cluster: $cluster
nodes: $nodes
from: $from
to: $to
) {
host
subCluster
metrics {
name
scope
metric {
timestep
unit {
base
prefix
}
series {
statistics {
min
avg
max
}
data
}
2022-06-22 11:20:57 +02:00
}
}
}
}
2023-07-03 09:01:28 +02:00
`;
2022-06-22 11:20:57 +02:00
$: nodeMetricsData = queryStore({
2023-05-10 16:35:21 +02:00
client: client,
query: nodeMetricsQuery,
2023-05-10 16:35:21 +02:00
variables: {
cluster: cluster,
nodes: [hostname],
from: from.toISOString(),
to: to.toISOString(),
2023-07-03 09:01:28 +02:00
},
2023-05-10 16:35:21 +02:00
});
2022-06-22 11:20:57 +02:00
let itemsPerPage = ccconfig.plot_list_jobsPerPage;
let page = 1;
let paging = { itemsPerPage, page };
let sorting = { field: "startTime", order: "DESC" };
$: filter = [
2023-07-03 09:01:28 +02:00
{ cluster: { eq: cluster } },
2023-07-03 09:45:09 +02:00
{ node: { contains: hostname } },
2023-07-03 09:01:28 +02:00
{ state: ["running"] },
// {startTime: {
// from: from.toISOString(),
2023-07-03 09:01:28 +02:00
// to: to.toISOString()
// }}
];
const nodeJobsQuery = gql`
query (
$filter: [JobFilter!]!
$sorting: OrderByInput!
$paging: PageRequest!
) {
jobs(filter: $filter, order: $sorting, page: $paging) {
# items {
# id
# jobId
# }
count
}
}
`;
$: nodeJobsData = queryStore({
client: client,
query: nodeJobsQuery,
2023-07-03 09:01:28 +02:00
variables: { paging, sorting, filter },
});
2023-07-03 09:01:28 +02:00
let metricUnits = {};
$: if ($nodeMetricsData.data) {
2023-07-03 09:01:28 +02:00
let thisCluster = clusters.find((c) => c.name == cluster);
if (thisCluster) {
for (let metric of thisCluster.metricConfig) {
if (metric.unit.prefix || metric.unit.base) {
2023-07-03 09:01:28 +02:00
metricUnits[metric.name] =
"(" +
(metric.unit.prefix ? metric.unit.prefix : "") +
(metric.unit.base ? metric.unit.base : "") +
")";
} else {
// If no unit defined: Omit Unit Display
metricUnits[metric.name] = "";
}
}
}
}
2023-07-03 09:01:28 +02:00
const dateToUnixEpoch = (rfc3339) => Math.floor(Date.parse(rfc3339) / 1000);
2022-06-22 11:20:57 +02:00
</script>
<Row>
{#if $initq.error}
<Card body color="danger">{$initq.error.message}</Card>
{:else if $initq.fetching}
2023-07-03 09:01:28 +02:00
<Spinner />
2022-06-22 11:20:57 +02:00
{:else}
<Col>
<InputGroup>
2023-07-03 09:01:28 +02:00
<InputGroupText><Icon name="hdd" /></InputGroupText>
2022-06-22 11:20:57 +02:00
<InputGroupText>{hostname} ({cluster})</InputGroupText>
</InputGroup>
</Col>
<Col>
2023-07-03 09:01:28 +02:00
{#if $nodeJobsData.fetching}
<Spinner />
{:else if $nodeJobsData.data}
Currently running jobs on this node: {$nodeJobsData.data.jobs
.count}
[
<a
href="/monitoring/jobs/?cluster={cluster}&state=running&node={hostname}"
target="_blank">View in Job List</a
> ]
{:else}
2023-07-03 09:01:28 +02:00
No currently running jobs.
{/if}
</Col>
2022-06-22 11:20:57 +02:00
<Col>
2023-07-03 09:01:28 +02:00
<TimeSelection bind:from bind:to />
2022-06-22 11:20:57 +02:00
</Col>
{/if}
</Row>
2023-07-03 09:01:28 +02:00
<br />
2022-06-22 11:20:57 +02:00
<Row>
<Col>
{#if $nodeMetricsData.error}
<Card body color="danger">{$nodeMetricsData.error.message}</Card>
{:else if $nodeMetricsData.fetching || $initq.fetching}
2023-07-03 09:01:28 +02:00
<Spinner />
2022-06-22 11:20:57 +02:00
{:else}
<PlotTable
let:item
let:width
renderFor="node"
2022-06-22 11:20:57 +02:00
itemsPerRow={ccconfig.plot_view_plotsPerRow}
items={$nodeMetricsData.data.nodeMetrics[0].metrics
2023-07-03 09:01:28 +02:00
.map((m) => ({
...m,
disabled: checkMetricDisabled(
m.name,
cluster,
$nodeMetricsData.data.nodeMetrics[0].subCluster
),
}))
.sort((a, b) => a.name.localeCompare(b.name))}
>
<h4 style="text-align: center; padding-top:15px;">
{item.name}
{metricUnits[item.name]}
</h4>
{#if item.disabled === false && item.metric}
<MetricPlot
2023-07-03 09:01:28 +02:00
{width}
height={300}
metric={item.name}
timestep={item.metric.timestep}
cluster={clusters.find((c) => c.name == cluster)}
subCluster={$nodeMetricsData.data.nodeMetrics[0]
.subCluster}
series={item.metric.series}
/>
{:else if item.disabled === true && item.metric}
2023-07-03 09:01:28 +02:00
<Card
style="margin-left: 2rem;margin-right: 2rem;"
body
color="info"
>Metric disabled for subcluster <code
>{item.name}:{$nodeMetricsData.data.nodeMetrics[0]
.subCluster}</code
></Card
>
{:else}
2023-07-03 09:01:28 +02:00
<Card
style="margin-left: 2rem;margin-right: 2rem;"
body
color="warning"
>No dataset returned for <code>{item.name}</code></Card
>
{/if}
2022-06-22 11:20:57 +02:00
</PlotTable>
{/if}
</Col>
</Row>