diff --git a/packages/frontend/src/lib/components/LiveAreaStackChart.svelte b/packages/frontend/src/lib/components/LiveAreaStackChart.svelte new file mode 100644 index 0000000..6a77570 --- /dev/null +++ b/packages/frontend/src/lib/components/LiveAreaStackChart.svelte @@ -0,0 +1,89 @@ + + + + + ({ + key, + data: data?.[key], + color: `var(--color-${color}-${shades[index % (shades.length - 1)]})`, + }))} + props={merge["props"]>, NonNullable["props"]>>( + { + area: { curve: curveCatmullRom }, + tooltip: { + root: { class: "preset-filled-surface-100-900!" }, + header: { + format: (x) => new Date(x).toLocaleTimeString(), + }, + }, + }, + props.props ?? {}, + )} +/> diff --git a/packages/frontend/src/lib/remotes/clusters.remote.ts b/packages/frontend/src/lib/remotes/clusters.remote.ts index 9c9891c..97509a7 100644 --- a/packages/frontend/src/lib/remotes/clusters.remote.ts +++ b/packages/frontend/src/lib/remotes/clusters.remote.ts @@ -5,6 +5,7 @@ import { ClusterIdParamSchema, GetClusterLogsQuerySchema, GetClusterSchema, + SseIntervalQuerySchema, type GetAggregateStatsDto, type GetClusterDto, type GetClusterLogsDto, @@ -242,40 +243,45 @@ export const getClustersLive = query.live(async function* () { } }); -export const getClustersStatsLive = query.live(async function* () { - const token = getRequestEvent().cookies.get("token"); +export const getClustersStatsLive = query.live( + SseIntervalQuerySchema, + async function* ({ interval }) { + const response = await fetch( + new URL(`/clusters/stats/stream?interval=${interval}`, env.API_URL), + { + headers: { + Accept: "text/event-stream", + Authorization: `Bearer ${getRequestEvent().cookies.get("token")}`, + }, + }, + ); - const response = await fetch(new URL("/clusters/stats/stream?interval=2", env.API_URL), { - headers: { - Accept: "text/event-stream", - Authorization: `Bearer ${token}`, - }, - }); + switch (response.status) { + case 200: { + if (!response.body) { + console.error(await response.text()); + return error(500, "An error occurred"); + } + + const chunks = response.body + .pipeThrough(new TextDecoderStream()) + .pipeThrough(new EventSourceParserStream()) + // @ts-ignore svelte-check false positive + .values(); + + for await (const chunk of chunks) + yield { ...(JSON.parse(chunk.data) as GetAggregateStatsDto), date: new Date() }; + return; + } + case 401: + return redirect(303, "/login"); - switch (response.status) { - case 200: { - if (!response.body) { + default: console.error(await response.text()); return error(500, "An error occurred"); - } - - const chunks = response.body - .pipeThrough(new TextDecoderStream()) - .pipeThrough(new EventSourceParserStream()) - // @ts-ignore svelte-check false positive - .values(); - - for await (const chunk of chunks) yield JSON.parse(chunk.data) as GetAggregateStatsDto; - return; } - case 401: - return redirect(303, "/login"); - - default: - console.error(await response.text()); - return error(500, "An error occurred"); - } -}); + }, +); export const startClusters = query.batch( "unchecked", diff --git a/packages/frontend/src/routes/(app)/stats/+layout.svelte b/packages/frontend/src/routes/(app)/stats/+layout.svelte index 58dccd8..05cb1d0 100644 --- a/packages/frontend/src/routes/(app)/stats/+layout.svelte +++ b/packages/frontend/src/routes/(app)/stats/+layout.svelte @@ -1,9 +1,12 @@ -
+{@render appbar(["Statistics"])} + +
{@render children()}
diff --git a/packages/frontend/src/routes/(app)/stats/+page.svelte b/packages/frontend/src/routes/(app)/stats/+page.svelte index b31e380..47314d7 100644 --- a/packages/frontend/src/routes/(app)/stats/+page.svelte +++ b/packages/frontend/src/routes/(app)/stats/+page.svelte @@ -1,66 +1,23 @@ -{#snippet card( - label: string, - icon: typeof Icon, - percentage: number, - value: string[], -)} - {@const Icon = icon} +
+
+ +
+
-
- - -
-

{label}

- {#each value as value} -

{value}

- {/each} -
-
- - - - - - + +
-{/snippet} - -
- {@render card("CPU", CpuIcon, cpu, [cpu.toPrecision(2) + "%"])} - {@render card("Memory", MemoryStickIcon, memory, [ - memory.toPrecision(2) + "%", - formatBytes(memoryUsage), - ])}
diff --git a/packages/frontend/src/routes/(app)/stats/components/CPU.svelte b/packages/frontend/src/routes/(app)/stats/components/CPU.svelte new file mode 100644 index 0000000..6c0931c --- /dev/null +++ b/packages/frontend/src/routes/(app)/stats/components/CPU.svelte @@ -0,0 +1,44 @@ + + + + + diff --git a/packages/frontend/src/routes/(app)/stats/components/Memory.svelte b/packages/frontend/src/routes/(app)/stats/components/Memory.svelte new file mode 100644 index 0000000..c1b9c6c --- /dev/null +++ b/packages/frontend/src/routes/(app)/stats/components/Memory.svelte @@ -0,0 +1,45 @@ + + + + +