Phase 2: Docker and OIDC auth

This commit is contained in:
2026-05-04 13:50:53 +02:00
parent 47baee854b
commit 4226628d5a
71 changed files with 9722 additions and 1347 deletions
+67 -34
View File
@@ -1,3 +1,12 @@
import {
Box,
Button,
Chip,
Divider,
Grid,
Stack,
Typography,
} from "@mui/material";
import {
useMonitoringStatus,
useMonitoringMetrics,
@@ -32,7 +41,6 @@ export function Monitoring() {
const samples = metrics?.samples ?? [];
const latest = samples.at(-1);
// Compute averages and peaks
const avg = (arr: number[]) =>
arr.length ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
const max = (arr: number[]) => (arr.length ? Math.max(...arr) : 0);
@@ -46,95 +54,120 @@ export function Monitoring() {
const diskWriteArr = samples.map((s) => s.disk_write_bps);
return (
<div className="space-y-8">
{/* Controls */}
<section className="flex items-center gap-4">
<span className="text-sm text-gray-600">
Collector:{" "}
<code className="bg-gray-100 px-1 rounded">
{status?.status ?? "unknown"}
</code>
</span>
<button
<Stack spacing={3}>
<Stack
direction="row"
spacing={1.5}
sx={{ alignItems: "center", flexWrap: "wrap" }}
>
<Typography variant="h5">Monitoring</Typography>
<Chip
label={status?.status ?? "unknown"}
color="primary"
variant="outlined"
/>
<Button
size="small"
variant="outlined"
onClick={() => start.mutate()}
className="px-3 py-1 text-sm rounded border hover:bg-gray-50"
disabled={start.isPending}
>
Start
</button>
<button
</Button>
<Button
size="small"
variant="outlined"
onClick={() => restart.mutate()}
className="px-3 py-1 text-sm rounded border hover:bg-gray-50"
disabled={restart.isPending}
>
Restart
</button>
<button
</Button>
<Button
size="small"
variant="outlined"
onClick={() => stop.mutate()}
className="px-3 py-1 text-sm rounded border hover:bg-gray-50"
disabled={stop.isPending}
>
Stop
</button>
</section>
</Button>
</Stack>
{/* Metrics summary */}
<section>
<div className="grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-7 gap-3">
<Grid container spacing={1.5}>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="CPU now"
value={latest ? `${latest.cpu_pct.toFixed(1)}%` : "-"}
subtext={`avg ${avg(cpuArr).toFixed(1)}%\npeak ${max(cpuArr).toFixed(1)}%`}
/>
</Grid>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="IO Wait"
value={latest ? `${(latest.iowait_pct ?? 0).toFixed(1)}%` : "-"}
subtext={`avg ${avg(iowArr).toFixed(1)}%\npeak ${max(iowArr).toFixed(1)}%`}
/>
</Grid>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="RAM now"
value={latest ? `${latest.mem_pct.toFixed(1)}%` : "-"}
subtext={`avg ${avg(memArr).toFixed(1)}%\npeak ${max(memArr).toFixed(1)}%`}
/>
</Grid>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="Net down"
value={latest ? formatRate(latest.net_rx_bytes_per_sec) : "-"}
subtext={`avg ${formatRate(avg(netDownArr))}\npeak ${formatRate(max(netDownArr))}`}
/>
</Grid>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="Net up"
value={latest ? formatRate(latest.net_tx_bytes_per_sec) : "-"}
subtext={`avg ${formatRate(avg(netUpArr))}\npeak ${formatRate(max(netUpArr))}`}
/>
</Grid>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="Disk read"
value={latest ? formatRate(latest.disk_read_bps) : "-"}
subtext={`avg ${formatRate(avg(diskReadArr))}\npeak ${formatRate(max(diskReadArr))}`}
/>
</Grid>
<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
<MetricCard
label="Disk write"
value={latest ? formatRate(latest.disk_write_bps) : "-"}
subtext={`avg ${formatRate(avg(diskWriteArr))}\npeak ${formatRate(max(diskWriteArr))}`}
/>
</div>
</section>
</Grid>
</Grid>
{/* Disk space */}
{disk && (
<section>
<div className="grid grid-cols-4 gap-3">
<Grid container spacing={1.5}>
<Grid size={{ xs: 6, md: 3 }}>
<MetricCard label="Disk used" value={formatBytes(disk.used)} />
</Grid>
<Grid size={{ xs: 6, md: 3 }}>
<MetricCard
label="Disk available"
value={formatBytes(disk.available)}
/>
</Grid>
<Grid size={{ xs: 6, md: 3 }}>
<MetricCard label="Disk total" value={formatBytes(disk.size)} />
</Grid>
<Grid size={{ xs: 6, md: 3 }}>
<MetricCard label="Used %" value={disk.used_pct} />
</div>
</section>
</Grid>
</Grid>
)}
{/* Charts */}
<section>
<Divider />
<Box>
<MonitoringCharts samples={samples} />
</section>
</div>
</Box>
</Stack>
);
}