feat(monitor): add alert monitoring page with KPI dashboard, alert list, and incident management

- Add Tauri plugins for file dialog and filesystem access
- Create Rust backend for processing Grafana alerts (pairing, KPI calculation)
- Add virtualized alert list with invalid toggle and incident attachment
- Add incident manager with create, attach, and detach functionality
- Add KPI dashboard showing coverage ratio, downtime, and invalid rate
- Add date-fns for date formatting
This commit is contained in:
Syahdan 2025-12-29 05:44:21 +07:00
parent ee3c0c156b
commit ea1c9105a7
15 changed files with 1757 additions and 19 deletions

View file

@ -0,0 +1,117 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import type { KpiMetrics } from "@/lib/types/alerts";
interface KpiDashboardProps {
kpis: KpiMetrics | null;
isLoading?: boolean;
}
export function KpiDashboard({ kpis, isLoading = false }: KpiDashboardProps) {
if (isLoading) {
return (
<div className="grid gap-4 md:grid-cols-3">
<Card className="rounded-none">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Error Coverage
</CardTitle>
</CardHeader>
<CardContent>
<Skeleton className="h-7 w-20 rounded-none" />
<Skeleton className="mt-1 h-4 w-32 rounded-none" />
</CardContent>
</Card>
<Card className="rounded-none">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Total Downtime
</CardTitle>
</CardHeader>
<CardContent>
<Skeleton className="h-7 w-20 rounded-none" />
</CardContent>
</Card>
<Card className="rounded-none">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Invalid Alerts
</CardTitle>
</CardHeader>
<CardContent>
<Skeleton className="h-7 w-20 rounded-none" />
<Skeleton className="mt-1 h-4 w-32 rounded-none" />
</CardContent>
</Card>
</div>
);
}
if (!kpis) {
return (
<Card className="rounded-none">
<CardContent className="pt-6 text-center text-xs text-muted-foreground">
No KPI data available
</CardContent>
</Card>
);
}
const coverageColor =
kpis.errorCoverageRatio > 80
? "text-green-500"
: kpis.errorCoverageRatio > 50
? "text-yellow-500"
: "text-destructive";
const invalidColor =
kpis.invalidAlertRatio < 10
? "text-green-500"
: kpis.invalidAlertRatio < 25
? "text-yellow-500"
: "text-destructive";
return (
<div className="grid gap-4 md:grid-cols-3">
<Card className="rounded-none">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Error Coverage</CardTitle>
</CardHeader>
<CardContent>
<div className={cn("text-2xl font-bold", coverageColor)}>
{kpis.errorCoverageRatio.toFixed(1)}%
</div>
<p className="text-xs text-muted-foreground">
{kpis.coveredIncidents} of {kpis.totalIncidents} incidents
</p>
</CardContent>
</Card>
<Card className="rounded-none">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Downtime</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{kpis.overallDowntimeFormatted}
</div>
</CardContent>
</Card>
<Card className="rounded-none">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Invalid Alerts</CardTitle>
</CardHeader>
<CardContent>
<div className={cn("text-2xl font-bold", invalidColor)}>
{kpis.invalidAlertRatio.toFixed(1)}%
</div>
<p className="text-xs text-muted-foreground">
{kpis.invalidAlerts} of {kpis.totalFiringAlerts} alerts
</p>
</CardContent>
</Card>
</div>
);
}