feat(observability): add Prometheus/Grafana/Loki/Alertmanager/Alloy stack and remove legacy Monitoring UI

This commit is contained in:
Developer
2026-06-16 11:08:32 +00:00
parent 615e02e970
commit e2ad731b5f
80 changed files with 5020 additions and 3665 deletions
-10
View File
@@ -26,13 +26,11 @@ import {
useActivity,
useDashboardShortcuts,
useDeleteDashboardShortcut,
useMonitoringOverview,
useSaveDashboardShortcut,
} from "../hooks/useDashboard";
import { useMonitoringSettings } from "../hooks/useSettings";
import type { DashboardShortcut, DashboardShortcutInput } from "../types";
import { NowPlaying } from "../components/NowPlaying";
import { MonitoringOverviewTable } from "../components/MonitoringOverviewTable";
import { SectionCard } from "../components/SectionCard";
import { DialogFooter } from "../components/DialogFooter";
import BackupDashboardWidget from "../components/BackupDashboardWidget";
@@ -325,7 +323,6 @@ export function Dashboard() {
const selectedJellyfinId =
activeJellyfinMachineId || jellyfinMachines[0]?.id || "";
const { data: activity } = useActivity(selectedJellyfinId || undefined);
const { data: monitoringOverview } = useMonitoringOverview();
const { data: shortcuts = [] } = useDashboardShortcuts();
const saveShortcut = useSaveDashboardShortcut();
const deleteShortcut = useDeleteDashboardShortcut();
@@ -438,13 +435,6 @@ export function Dashboard() {
) : null}
</SectionCard>
<SectionCard
title="Monitoring overview"
description="10-minute averages and fleet status across all configured machines."
>
<MonitoringOverviewTable overview={monitoringOverview} embedded />
</SectionCard>
<BackupDashboardWidget />
<ShortcutDialog
-106
View File
@@ -1,106 +0,0 @@
import { useMemo, useState } from "react";
import { Alert, Button, Stack, Tab, Typography } from "@mui/material";
import { useNavigate } from "react-router-dom";
import {
useMonitoringMachines,
useMonitoringPoller,
} from "../hooks/useMonitoring";
import { useMonitoringOverview } from "../hooks/useDashboard";
import { MachineMonitoringSection } from "../components/MachineMonitoringSection";
import { MonitoringOverviewTable } from "../components/MonitoringOverviewTable";
import { SectionCard } from "../components/SectionCard";
import { TabbedCard } from "../components/TabbedCard";
type MonitoringTab = "overview" | string;
export function Monitoring() {
const { data: machines = [], isLoading, error } = useMonitoringMachines();
const { data: poller } = useMonitoringPoller();
const { data: overview } = useMonitoringOverview();
const navigate = useNavigate();
const [tab, setTab] = useState<MonitoringTab>("overview");
const selectedMachine = useMemo(
() => machines.find((machine) => machine.id === tab) ?? null,
[machines, tab],
);
return (
<Stack spacing={2.25}>
<Stack spacing={0.5}>
<Typography variant="h5" sx={{ fontWeight: 800 }}>
Monitoring
</Typography>
<Typography variant="body2" color="text.secondary">
Review fleet health first, then switch to a machine-specific tab.
</Typography>
</Stack>
{error ? <Alert severity="error">{String(error)}</Alert> : null}
{isLoading ? (
<Alert severity="info">Loading monitoring machines...</Alert>
) : null}
<TabbedCard
value={tab}
onChange={setTab}
tabs={[
<Tab key="overview" value="overview" label="Overview" />,
...machines.map((machine) => (
<Tab key={machine.id} value={machine.id} label={machine.name} />
)),
]}
contentSx={{ p: 1.5 }}
>
{tab === "overview" ? (
<Stack spacing={1.5}>
<Stack
direction="row"
spacing={1}
sx={{ alignItems: "center", flexWrap: "wrap" }}
>
<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
Fleet overview
</Typography>
<Typography variant="caption" color="text.secondary">
{poller?.worker_running ? "running" : "stopped"}
</Typography>
</Stack>
{!isLoading && machines.length === 0 ? (
<Alert
severity="warning"
action={
<Button
color="inherit"
size="small"
onClick={() => navigate("/settings")}
>
Open Settings
</Button>
}
>
No monitoring machines are configured yet.
</Alert>
) : overview ? (
<MonitoringOverviewTable overview={overview} embedded />
) : (
<Alert severity="info">Loading fleet overview...</Alert>
)}
</Stack>
) : selectedMachine ? (
<SectionCard
title={selectedMachine.name}
description={
selectedMachine.mode === "local"
? "Local API host"
: `${selectedMachine.username || "user"}@${selectedMachine.host || "host"}:${selectedMachine.port}`
}
>
<MachineMonitoringSection machine={selectedMachine} />
</SectionCard>
) : null}
</TabbedCard>
</Stack>
);
}