import { useMemo, useState, type ElementType, type ReactNode } from "react";
import { Link } from "react-router-dom";
import {
Activity,
AlertTriangle,
Bell,
CheckCircle2,
ChevronDown,
ExternalLink,
Gauge,
Inbox,
Radio,
RefreshCw,
Server,
ServerOff,
XCircle,
} from "lucide-react";
import {
useAlertmanagerAlerts,
useAlertmanagerStatus,
useGrafanaStatus,
usePrometheusStatus,
usePrometheusTargets,
useMonitoringMachines,
} from "../hooks/useObservability";
import { useServiceInstances } from "../hooks/useServices";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import type {
AlertmanagerAlert,
MonitoringMachine,
PrometheusTarget,
} from "../types";
function severityVariant(
severity: string,
): "default" | "secondary" | "destructive" | "outline" {
switch (severity.toLowerCase()) {
case "critical":
return "destructive";
case "warning":
return "default";
case "info":
return "secondary";
default:
return "outline";
}
}
function HealthCard({
title,
status,
detail,
icon: Icon,
isLoading,
}: {
title: string;
status: "ok" | "warning" | "error" | "unknown";
detail: string;
icon: ElementType;
isLoading?: boolean;
}) {
const statusIcon =
status === "ok" ? (
) : status === "warning" ? (
) : status === "error" ? (
) : (
);
return (
{title}
{isLoading ? : statusIcon}
{status}
{detail}
);
}
function EmptyState({
icon: Icon,
title,
description,
action,
}: {
icon: ElementType;
title: string;
description: string;
action?: ReactNode;
}) {
return (
{title}
{description}
{action ?
{action}
: null}
);
}
function QueryError({
label,
error,
refetch,
}: {
label: string;
error: Error | null;
refetch: () => void;
}) {
if (!error) return null;
return (
{label} failed
{error.message}
);
}
function AlertItem({ alert }: { alert: AlertmanagerAlert }) {
return (
{alert.name}
{alert.severity}
{alert.summary || alert.description}
{alert.active_since && (
Since {new Date(alert.active_since).toLocaleString()}
)}
{alert.description && (
Description:{" "}
{alert.description}
)}
{alert.job_name && (
Job: {alert.job_name}
)}
{alert.category && (
Category: {alert.category}
)}
State: {alert.state}
Since:{" "}
{alert.active_since
? new Date(alert.active_since).toLocaleString()
: "unknown"}
{alert.labels && Object.keys(alert.labels).length > 0 && (
{Object.entries(alert.labels).map(([key, value]) => (
{key}={value}
))}
)}
);
}
function TargetsTable({ targets }: { targets: PrometheusTarget[] }) {
return (
{targets.map((target, idx) => (
{target.targets.join(", ")}
{target.labels && Object.keys(target.labels).length > 0 && (
{Object.entries(target.labels).map(([key, value]) => (
{key}: {value}
))}
)}
))}
);
}
function GrafanaLinkCard({
title,
description,
href,
}: {
title: string;
description: string;
href: string;
}) {
return (
);
}
export function ObservabilityPage() {
const {
data: alertsSummary,
isLoading: alertsLoading,
error: alertsError,
refetch: refetchAlerts,
} = useAlertmanagerAlerts();
const {
data: alertmanagerStatus,
isLoading: statusLoading,
error: statusError,
refetch: refetchStatus,
} = useAlertmanagerStatus();
const {
data: grafanaStatus,
isLoading: grafanaLoading,
error: grafanaError,
refetch: refetchGrafana,
} = useGrafanaStatus();
const {
data: prometheusStatus,
isLoading: prometheusLoading,
error: prometheusError,
refetch: refetchPrometheus,
} = usePrometheusStatus();
const {
data: prometheusTargets,
isLoading: targetsLoading,
error: targetsError,
refetch: refetchTargets,
} = usePrometheusTargets();
const {
data: machines = [],
isLoading: machinesLoading,
error: machinesError,
refetch: refetchMachines,
} = useMonitoringMachines();
const { data: grafanaServices = [] } = useServiceInstances("grafana");
const [selectedMachineId, setSelectedMachineId] = useState("");
const grafanaService =
grafanaServices.find((s) => s.enabled) ?? grafanaServices[0];
const GRAFANA_BASE_URL =
(grafanaService?.config?.base_url as string | undefined) ?? "";
const selectedMachine = useMemo(
() =>
machines.find((m) => m.id === selectedMachineId) ?? machines[0] ?? null,
[machines, selectedMachineId],
);
const nodeExporterDashboardUrl = useMemo(() => {
if (!selectedMachine || !GRAFANA_BASE_URL) return "";
const instance = `${selectedMachine.host || "localhost"}:9100`;
return `${GRAFANA_BASE_URL}/d/node-exporter-overview/node-exporter-overview?kiosk&var-instance=${encodeURIComponent(instance)}`;
}, [selectedMachine, GRAFANA_BASE_URL]);
const logsUrl = useMemo(() => {
if (!selectedMachine || !GRAFANA_BASE_URL) return "";
const container =
selectedMachine.mode === "local" ? "backend" : selectedMachine.name;
return `${GRAFANA_BASE_URL}/explore?orgId=1&left=${encodeURIComponent(
JSON.stringify({
datasource: "Loki",
queries: [{ refId: "A", expr: `{container="${container}"}` }],
range: { from: "now-1h", to: "now" },
}),
)}`;
}, [selectedMachine, GRAFANA_BASE_URL]);
const alertmanagerStatusDetail = alertmanagerStatus?.up
? alertmanagerStatus.version
? `version ${alertmanagerStatus.version}`
: "reachable"
: "unreachable";
const targetsCount = prometheusTargets?.length ?? 0;
const targetsStatus: "ok" | "warning" | "error" | "unknown" = targetsLoading
? "unknown"
: targetsError
? "error"
: targetsCount > 0
? "ok"
: "warning";
const alertStatus: "ok" | "warning" | "error" | "unknown" = alertsLoading
? "unknown"
: alertsError
? "error"
: (alertsSummary?.total ?? 0) > 0
? alertsSummary?.alerts.some((a) => a.severity === "critical")
? "error"
: "warning"
: "ok";
const machinesStatus: "ok" | "warning" | "error" | "unknown" = machinesLoading
? "unknown"
: machinesError
? "error"
: machines.length > 0
? "ok"
: "warning";
return (
Observability
Unified view of metrics, logs, and alerts from Prometheus, Loki, and
Alertmanager. Deep dashboards live in Grafana.
{statusError && (
)}
{alertsError && (
)}
{targetsError && (
)}
{machinesError && (
)}
{grafanaError && (
)}
{prometheusError && (
)}
{alertsSummary?.error && (
Alertmanager unreachable
The UI cannot reach Alertmanager right now. Alerts shown here may be
stale.
)}
Recent Alerts
{alertsLoading ? (
) : !alertsSummary || alertsSummary.total === 0 ? (
) : (
<>
{alertsSummary.alerts.map((alert, idx) => (
))}
{alertsSummary.total > alertsSummary.alerts.length && (
{alertsSummary.total - alertsSummary.alerts.length} more
alert
{alertsSummary.total - alertsSummary.alerts.length === 1
? ""
: "s"}{" "}
in Alertmanager
)}
>
)}
Prometheus Targets
{targetsLoading ? (
) : !prometheusTargets || prometheusTargets.length === 0 ? (
Open Settings
}
/>
) : (
)}
Machine Dashboard
{selectedMachine ? (
GRAFANA_BASE_URL ? (
<>
>
) : (
Open Services
}
/>
)
) : (
Open Settings
}
/>
)}
);
}