2024-07-25 17:10:00 +02:00
<!--
@component System-View subcomponent; renders all current metrics for specified node
Properties:
- `cluster String`: Currently selected cluster
- `hostname String`: Currently selected host (== node)
- `from Date?`: Custom Time Range selection 'from' [Default: null]
- `to Date?`: Custom Time Range selection 'to' [Default: null]
-->
2022-06-22 11:20:57 +02:00
< script >
2024-07-26 12:34:18 +02:00
import { getContext } from "svelte";
2024-03-09 10:30:40 +01:00
import {
Row,
Col,
2024-10-02 14:37:32 +02:00
Input,
2024-03-09 10:30:40 +01:00
InputGroup,
InputGroupText,
Icon,
Spinner,
Card,
} from "@sveltestrap/sveltestrap";
2024-07-26 12:34:18 +02:00
import {
queryStore,
gql,
getContextClient,
} from "@urql/svelte";
import {
init,
checkMetricDisabled,
2024-08-08 12:28:36 +02:00
} from "./generic/utils.js";
2024-10-02 17:48:46 +02:00
import PlotGrid from "./generic/PlotGrid.svelte";
2024-07-26 12:34:18 +02:00
import MetricPlot from "./generic/plots/MetricPlot.svelte";
import TimeSelection from "./generic/select/TimeSelection.svelte";
import Refresher from "./generic/helper/Refresher.svelte";
2022-06-22 11:20:57 +02:00
2024-03-09 10:30:40 +01:00
export let cluster;
export let hostname;
export let from = null;
export let to = null;
2022-06-22 11:20:57 +02:00
2024-03-09 10:30:40 +01:00
const { query : initq } = init();
2022-06-22 11:20:57 +02:00
2024-03-09 10:30:40 +01:00
if (from == null || to == null) {
to = new Date(Date.now());
from = new Date(to.getTime());
2024-10-14 18:37:48 +02:00
from.setHours(from.getHours() - 4);
2024-03-09 10:30:40 +01:00
}
2022-06-22 11:20:57 +02:00
2024-07-22 15:41:33 +02:00
const initialized = getContext("initialized")
const globalMetrics = getContext("globalMetrics")
2024-03-09 10:30:40 +01:00
const ccconfig = getContext("cc-config");
const clusters = getContext("clusters");
const client = getContextClient();
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
}
2024-03-09 10:30:40 +01:00
}
2022-06-22 11:20:57 +02:00
}
2024-03-09 10:30:40 +01:00
}
}
`;
2022-06-22 11:20:57 +02:00
2024-03-09 10:30:40 +01:00
$: nodeMetricsData = queryStore({
client: client,
query: nodeMetricsQuery,
variables: {
cluster: cluster,
nodes: [hostname],
from: from.toISOString(),
to: to.toISOString(),
},
});
2022-06-22 11:20:57 +02:00
2024-09-02 17:54:45 +02:00
const paging = { itemsPerPage : 50 , page : 1 } ;
const sorting = { field : "startTime" , type : "col" , order : "DESC" } ;
const filter = [
2024-03-09 10:30:40 +01:00
{ cluster : { eq : cluster } } ,
{ node : { contains : hostname } } ,
{ state : [ "running" ] } ,
];
2023-06-30 12:01:27 +02:00
2024-03-09 10:30:40 +01:00
const nodeJobsQuery = gql`
query (
$filter: [JobFilter!]!
$sorting: OrderByInput!
$paging: PageRequest!
) {
jobs(filter: $filter, order: $sorting, page: $paging) {
count
}
}
`;
2023-06-30 12:01:27 +02:00
2024-03-09 10:30:40 +01:00
$: nodeJobsData = queryStore({
client: client,
query: nodeJobsQuery,
variables: { paging , sorting , filter } ,
});
2023-06-30 12:01:27 +02:00
2024-07-22 15:41:33 +02:00
let systemUnits = {} ;
function loadUnits(isInitialized) {
if (!isInitialized) return
const systemMetrics = [...globalMetrics.filter((gm) => gm?.availability.find((av) => av.cluster == cluster))]
for (let sm of systemMetrics) {
systemUnits[sm.name] = (sm?.unit?.prefix ? sm.unit.prefix : "") + (sm?.unit?.base ? sm.unit.base : "")
2023-03-30 15:21:35 +02:00
}
2024-03-09 10:30:40 +01:00
}
2023-06-14 15:32:35 +02:00
2024-07-22 15:41:33 +02:00
$: loadUnits($initialized)
2022-06-22 11:20:57 +02:00
< / script >
2024-10-02 14:48:21 +02:00
< Row cols = {{ xs : 2 , lg : 4 }} >
2024-03-09 10:30:40 +01:00
{ #if $initq . error }
< Card body color = "danger" > { $initq . error . message } </ Card >
{ :else if $initq . fetching }
< Spinner / >
{ : else }
2024-10-02 14:37:32 +02:00
<!-- Node Col -->
2024-03-09 10:30:40 +01:00
< Col >
< InputGroup >
< InputGroupText > < Icon name = "hdd" / > < / InputGroupText >
2024-10-02 14:37:32 +02:00
< InputGroupText > Selected Node< / InputGroupText >
2024-10-16 13:05:03 +02:00
< Input style = "background-color: white;" type = "text" value = " { hostname } [ { cluster } ( { $nodeMetricsData ? . data ? $nodeMetricsData . data . nodeMetrics [ 0 ]. subCluster : '' } )]" disabled />
2024-03-09 10:30:40 +01:00
< / InputGroup >
< / Col >
2024-10-02 14:37:32 +02:00
<!-- Time Col -->
< Col >
< TimeSelection bind:from bind:to / >
< / Col >
<!-- Concurrent Col -->
2024-10-02 14:48:21 +02:00
< Col class = "mt-2 mt-lg-0" >
2024-03-09 10:30:40 +01:00
{ #if $nodeJobsData . fetching }
2023-07-03 09:01:28 +02:00
< Spinner / >
2024-03-09 10:30:40 +01:00
{ :else if $nodeJobsData . data }
2024-10-14 18:37:48 +02:00
< InputGroup >
< InputGroupText > < Icon name = "activity" / > < / InputGroupText >
< InputGroupText > Activity< / InputGroupText >
< Input style = "background-color: white;" type = "text" value = " { $nodeJobsData . data . jobs . count } Jobs" disabled />
< a title = "Show jobs running on this node" href = "/monitoring/jobs/?cluster= { cluster } &state=running&node= { hostname } " target = "_blank" class = "btn btn-outline-secondary" role = "button" aria-disabled = "true" >
< Icon name = "view-list" / > Show List
< / a >
< / InputGroup >
2024-03-09 10:30:40 +01:00
{ : else }
2024-10-14 18:37:48 +02:00
< InputGroup >
< InputGroupText > < Icon name = "activity" / > < / InputGroupText >
< InputGroupText > Activity< / InputGroupText >
< Input type = "text" value = "No running jobs." disabled / >
< / InputGroup >
2024-03-09 10:30:40 +01:00
{ /if }
< / Col >
2024-10-02 14:37:32 +02:00
<!-- Refresh Col -->
2024-10-02 14:48:21 +02:00
< Col class = "mt-2 mt-lg-0" >
2024-03-09 10:30:40 +01:00
< Refresher
2024-07-25 17:10:00 +02:00
on:refresh={() => {
2024-03-09 10:30:40 +01:00
const diff = Date.now() - to;
from = new Date(from.getTime() + diff);
to = new Date(to.getTime() + diff);
}}
/>
< / Col >
{ /if }
2022-06-22 11:20:57 +02:00
< / Row >
2023-07-03 09:01:28 +02:00
< br / >
2022-06-22 11:20:57 +02:00
< Row >
2024-03-09 10:30:40 +01:00
< Col >
{ #if $nodeMetricsData . error }
< Card body color = "danger" > { $nodeMetricsData . error . message } </ Card >
{ :else if $nodeMetricsData . fetching || $initq . fetching }
< Spinner / >
{ : else }
2024-10-02 17:48:46 +02:00
< PlotGrid
2024-03-09 10:30:40 +01:00
let:item
itemsPerRow={ ccconfig . plot_view_plotsPerRow }
items={ $nodeMetricsData . data . nodeMetrics [ 0 ]. metrics
.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 }
2024-07-22 15:41:33 +02:00
{ systemUnits [ item . name ] ? "(" + systemUnits [ item . name ] + ")" : "" }
2024-03-09 10:30:40 +01:00
< / h4 >
{ #if item . disabled === false && item . metric }
< MetricPlot
metric={ item . name }
timestep={ item . metric . timestep }
cluster={ clusters . find (( c ) => c . name == cluster )}
subCluster={ $nodeMetricsData . data . nodeMetrics [ 0 ]. subCluster }
series={ item . metric . series }
forNode={ true }
/>
{ :else if item . disabled === true && item . metric }
< 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
>
2022-06-22 11:20:57 +02:00
{ : else }
2024-03-09 10:30:40 +01:00
< Card
style="margin-left: 2rem;margin-right: 2rem;"
body
color="warning"
>No dataset returned for < code > { item . name } </ code > < /Card
>
2022-06-22 11:20:57 +02:00
{ /if }
2024-10-02 17:48:46 +02:00
< / PlotGrid >
2024-03-09 10:30:40 +01:00
{ /if }
< / Col >
2022-06-22 11:20:57 +02:00
< / Row >