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 (
{title}
{description}
); } 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 } /> )}
); }