Benaah's picture
Upload folder using huggingface_hub
fecff63 verified
Raw History Blame Contribute Delete
7.53 kB
"use client";
import React from "react";
import { AlertCircle, Database, Clock, AlertTriangle } from "lucide-react";
import { trpc } from "@/lib/trpc";
import { cn } from "@/lib/utils";
import { AdminHeader } from "@/components/shell/AdminHeader";
import { Card, CardContent, CardHeader, CardTitle } from "@micprotocol/ui";
import { Badge } from "@micprotocol/ui";
import { Button } from "@micprotocol/ui";
import { ago } from "@/lib/utils";
export default function ObservabilityErrorsPage() {
const { data: errors, isLoading } = trpc.audit.list.useQuery(
{ limit: 50 },
{ refetchInterval: 30_000 },
);
const items = errors?.items ?? [];
const total = items.length;
const critical = items.filter((e: any) => e.severity === "critical").length;
const unresolved = items.filter((e: any) => !e.resolved).length;
const today = items.filter((e: any) => new Date(e.createdAt).toDateString() === new Date().toDateString()).length;
return (
<div className="animate-fade-in">
<AdminHeader
title="Error Hub"
subtitle="Platform errors, exceptions, and stack traces"
refreshing={isLoading}
/>
<div className="space-y-6 p-6">
{/* KPI strip */}
<div className="grid gap-4 sm:grid-cols-4">
<Card className="p-5 border border-[var(--border-color)]">
<p className="text-xs font-mono text-[var(--text-secondary)] uppercase tracking-wide">Total Errors</p>
<p className="mt-2 font-display text-2xl font-bold text-[var(--color-error)]">{total}</p>
</Card>
<Card className="p-5 border border-[var(--border-color)]">
<p className="text-xs font-mono text-[var(--text-secondary)] uppercase tracking-wide">Critical</p>
<p className="mt-2 font-display text-2xl font-bold text-[var(--color-error)]">{critical}</p>
</Card>
<Card className="p-5 border border-[var(--border-color)]">
<p className="text-xs font-mono text-[var(--text-secondary)] uppercase tracking-wide">Unresolved</p>
<p className="mt-2 font-display text-2xl font-bold text-[var(--color-warning)]">{unresolved}</p>
</Card>
<Card className="p-5 border border-[var(--border-color)]">
<p className="text-xs font-mono text-[var(--text-secondary)] uppercase tracking-wide">Today</p>
<p className="mt-2 font-display text-2xl font-bold text-[var(--color-info)]">{today}</p>
</Card>
</div>
{/* Errors table */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<AlertCircle className="size-4 text-[var(--color-error)]" /> Recent Errors
</CardTitle>
</CardHeader>
<CardContent className="p-0">
<div className="-mx-4 -my-2 overflow-x-auto">
<table className="w-full text-left border-collapse">
<thead>
<tr className="border-b border-[var(--border-color-subtle)]">
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium w-24">Error ID</th>
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium w-24">Message</th>
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium text-center w-20">Severity</th>
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium text-center w-20">Status</th>
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium w-24">Source</th>
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium text-right w-28">Occurred</th>
<th className="pb-3 text-[var(--text-tertiary)] text-xs uppercase tracking-wider font-medium text-right w-24">Actions</th>
</tr>
</thead>
<tbody>
{isLoading ? (
[...Array(5)].map((_, i) => (
<tr key={i} className="border-b border-[var(--border-color-subtle)]">
<td colSpan={7} className="py-12 text-center text-[var(--text-tertiary)]">
<div className="skeleton w-full h-16 mx-auto max-w-xs" />
</td>
</tr>
))
) : items.length === 0 ? (
<tr>
<td colSpan={7} className="py-12 text-center text-[var(--text-tertiary)]">
No errors recorded. Platform is healthy.
</td>
</tr>
) : (
items.map((e: any) => (
<tr key={e.id} className="border-b border-[var(--border-color-subtle)] hover:bg-[var(--bg-tertiary)]/30 transition-colors">
<td className="py-4 font-mono text-xs text-[var(--text-secondary)]">
{e.id.slice(0, 8)}…
</td>
<td className="py-4 text-xs text-[var(--text-secondary)] truncate" style={{ maxWidth: 220 }}>
{e.message ?? "—"}
</td>
<td className="py-4 text-xs text-center">
<Badge className={cn("capitalize text-xs", severityClass(e.severity))}>
{e.severity}
</Badge>
</td>
<td className="py-4 text-xs text-center">
<Badge className={cn("capitalize text-xs", e.resolved ? "bg-[var(--color-success)]/20 border-[var(--color-success)]/30 text-[var(--color-success)]" : "border-transparent text-[var(--text-tertiary)]")}>
{e.resolved ? "resolved" : "open"}
</Badge>
</td>
<td className="py-4 text-xs text-[var(--text-secondary)] font-mono truncate" style={{ maxWidth: 150 }}>
{e.source ?? "—"}
</td>
<td className="py-4 text-xs text-[var(--text-tertiary)] text-right">
{new Date(e.createdAt).toLocaleString()}
</td>
<td className="py-4 text-sm text-right">
<Button variant="ghost" size="sm" disabled={e.resolved} onClick={() => {}}>
<AlertTriangle size={14} className="mr-1" />
</Button>
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</CardContent>
</Card>
</div>
</div>
);
}
function severityClass(s: string): string {
switch (s) {
case "critical": return "bg-[var(--color-error)] border-[var(--color-error)] text-[var(--text-primary)]";
case "high": return "bg-[var(--color-error)]/10 border-[var(--color-error)]/20 text-[var(--color-error)]";
case "medium": return "bg-[var(--color-warning)]/10 border-[var(--color-warning)]/20 text-[var(--color-warning)]";
case "low": return "bg-[var(--color-info)]/10 border-[var(--color-info)]/20 text-[var(--color-info)]";
default: return "border-transparent";
}
}