Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions ui/src/components/docker/container-stats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

import { DataTable, SortableHeader } from "@/ui/data-table";

import { Group, Text } from "@mantine/core";
import DockerResourceLink from "@/components/docker/link";
import { filterBySplit } from "@/lib/utils";
import { Types } from "komodo_client";

export interface ContainerStatsProps {
containers: Types.ContainerListItem[];
search: string;
}

export default function ContainerStats({containers, search}: ContainerStatsProps) {
const filtered = filterBySplit(
containers,
search,
(container) => container.name,
);
return (
<DataTable
sortDescFirst
mah="min(400px, calc(100vh - 320px))"
tableKey="container-stats"
data={filtered}
columns={[
{
accessorKey: "name",
size: 200,
header: ({ column }) => (
<SortableHeader column={column} title="Name" />
),
cell: ({ row }) => (
<DockerResourceLink
type="Container"
serverId={row.original.server_id || ""}
name={row.original.name}
/>
),
},
{
accessorKey: "stats.cpu_perc",
size: 100,
header: ({ column }) => (
<SortableHeader column={column} title="CPU" />
),
},
{
accessorKey: "stats.mem_perc",
size: 200,
header: ({ column }) => (
<SortableHeader column={column} title="Memory" />
),
cell: ({ row }) => (
<Group gap="xs">
<Text>{row.original.stats?.mem_perc}</Text>
<Text c="muted" size="sm">
({row.original.stats?.mem_usage})
</Text>
</Group>
),
},
{
accessorKey: "stats.net_io",
size: 150,
header: ({ column }) => (
<SortableHeader column={column} title="Net I/O" />
),
},
{
accessorKey: "stats.block_io",
size: 150,
header: ({ column }) => (
<SortableHeader column={column} title="Block I/O" />
),
},
{
accessorKey: "stats.pids",
size: 100,
header: ({ column }) => (
<SortableHeader column={column} title="PIDs" />
),
},
]}
/>
);
}
119 changes: 23 additions & 96 deletions ui/src/resources/server/stats/containers.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { useRead } from "@/lib/hooks";
import { DataTable, SortableHeader } from "@/ui/data-table";
import Section from "@/ui/section";
import ShowHideButton from "@/ui/show-hide-button";
import { Group, Text } from "@mantine/core";
import { useLocalStorage } from "@mantine/hooks";
import { useState } from "react";
import { filterBySplit } from "@/lib/utils";
import DockerResourceLink from "@/components/docker/link";
import { useIsServerAvailable } from "../hooks";
import ContainerStats from "@/components/docker/container-stats";
import SearchInput from "@/ui/search-input";
import { ICONS } from "@/theme/icons";
import Section from "@/ui/section";
import ShowHideButton from "@/ui/show-hide-button";
import { Group } from "@mantine/core";

export default function ServerContainerStats({ id }: { id: string }) {
const [search, setSearch] = useState("");
Expand All @@ -27,95 +25,24 @@ export default function ServerContainerStats({ id }: { id: string }) {
enabled: isServerAvailable && show,
},
).data?.filter((c) => c.stats);
const filtered = filterBySplit(
containers,
search,
(container) => container.name,
);
return (
<Section
withBorder
title="Containers"
icon={<ICONS.Container size="1.3rem" />}
titleRight={
<Group ml={{ sm: "xl" }}>
<SearchInput
value={search}
onSearch={setSearch}
w={{ base: 200, lg: 300 }}
/>
<ShowHideButton show={show} setShow={setShow} />
</Group>
}
onHeaderClick={() => setShow((s) => !s)}
>
{show && (
<DataTable
sortDescFirst
mah="min(400px, calc(100vh - 320px))"
tableKey="container-stats"
data={filtered}
columns={[
{
accessorKey: "name",
size: 200,
header: ({ column }) => (
<SortableHeader column={column} title="Name" />
),
cell: ({ row }) => (
<DockerResourceLink
type="Container"
serverId={id}
name={row.original.name}
/>
),
},
{
accessorKey: "stats.cpu_perc",
size: 100,
header: ({ column }) => (
<SortableHeader column={column} title="CPU" />
),
},
{
accessorKey: "stats.mem_perc",
size: 200,
header: ({ column }) => (
<SortableHeader column={column} title="Memory" />
),
cell: ({ row }) => (
<Group gap="xs">
<Text>{row.original.stats?.mem_perc}</Text>
<Text c="muted" size="sm">
({row.original.stats?.mem_usage})
</Text>
</Group>
),
},
{
accessorKey: "stats.net_io",
size: 150,
header: ({ column }) => (
<SortableHeader column={column} title="Net I/O" />
),
},
{
accessorKey: "stats.block_io",
size: 150,
header: ({ column }) => (
<SortableHeader column={column} title="Block I/O" />
),
},
{
accessorKey: "stats.pids",
size: 100,
header: ({ column }) => (
<SortableHeader column={column} title="PIDs" />
),
},
]}
/>
)}
</Section>
);
<Section
withBorder
title="Containers"
icon={<ICONS.Container size="1.3rem" />}
titleRight={
<Group ml={{ sm: "xl" }}>
<SearchInput
value={search}
onSearch={setSearch}
w={{ base: 200, lg: 300 }}
/>
<ShowHideButton show={show} setShow={setShow} />
</Group>
}
onHeaderClick={() => setShow((s) => !s)}
>
<ContainerStats containers={containers || []} search={search} />
</Section>
)
}
37 changes: 37 additions & 0 deletions ui/src/resources/stack/stats/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useRead } from "@/lib/hooks";
import { Types } from "komodo_client";
import { ReactNode, useState } from "react";
import { useStack } from "..";
import ContainerStats from "@/components/docker/container-stats";
import Section from "@/ui/section";
import { Group } from "@mantine/core";
import SearchInput from "@/ui/search-input";

export default function StackContainerStats({ id, titleOther }: { id: string, titleOther: ReactNode }) {
const [search, setSearch] = useState("");
const isStackAvailable = useStack(id)?.info.state !== Types.StackState.Down;
const containers = useRead(
"ListStackServices",
{
stack: id,
},
{
enabled: isStackAvailable,
},
).data?.map((c) => c.container).filter(c => c !== undefined);
return (
<Section titleOther={titleOther}>
<Section title="Container Stats" titleRight={
<Group ml={{ sm: "xl" }}>
<SearchInput
value={search}
onSearch={setSearch}
w={{ base: 200, lg: 300 }}
/>
</Group>
}>
<ContainerStats search={search} containers={containers || []} />
</Section>
</Section>
)
}
10 changes: 9 additions & 1 deletion ui/src/resources/stack/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ import StackInfo from "./info";
import StackServices from "./services";
import StackLog from "./log";
import TerminalSection from "@/components/terminal/section";
import StackContainerStats from "./stats/container";

type StackTabsView = "Config" | "Info" | "Services" | "Log" | "Terminals";
type StackTabsView = "Config" | "Info" | "Services" | "Log" | "Terminals" | "Stats";

export default function StackTabs({ id }: { id: string }) {
const [_view, setView] = useLocalStorage<StackTabsView>({
Expand Down Expand Up @@ -87,6 +88,10 @@ export default function StackTabs({ id }: { id: string }) {
hidden: !specificTerminal,
icon: ICONS.Terminal,
},
{
value: "Stats",
icon: ICONS.Stats,
},
],
[
hideInfo,
Expand Down Expand Up @@ -139,6 +144,9 @@ export default function StackTabs({ id }: { id: string }) {
/>
);
break;
case "Stats":
View = <StackContainerStats id={id} titleOther={Selector} />;
break;
}

return (
Expand Down