Fix frontend/backend type mismatches in monitoring

TypeScript types now match Go backend JSON field names:
- MemoryStats: used_bytes, total_bytes, usage_percent, heap_alloc, heap_sys, heap_inuse
- DiskStats: used_bytes, total_bytes, free_bytes, usage_percent
- RuntimeStats: num_gc, last_gc_pause_ns
- HTTPStats: requests_total, requests_per_minute
- EndpointStats: error_rate (ratio), p95_latency_ms
- AsynqStats: removed total_* aggregates (calculated in frontend)

Updated components to use correct field names and calculate
aggregates where needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-09 10:56:47 -06:00
parent eb127fda20
commit 3f2b5415ed
4 changed files with 66 additions and 68 deletions

View File

@@ -41,9 +41,9 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
<Activity className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{(stats.total_requests ?? 0).toLocaleString()}</div>
<div className="text-2xl font-bold">{(stats.requests_total ?? 0).toLocaleString()}</div>
<p className="text-xs text-muted-foreground">
{(stats.requests_per_second ?? 0).toFixed(2)} req/s
{(stats.requests_per_minute ?? 0).toFixed(2)} req/min
</p>
</CardContent>
</Card>
@@ -55,9 +55,6 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{formatLatency(stats.avg_latency_ms)}</div>
<p className="text-xs text-muted-foreground">
P95: {formatLatency(stats.p95_latency_ms)}
</p>
</CardContent>
</Card>
@@ -67,10 +64,7 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
<AlertTriangle className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{formatPercent(stats.error_rate)}</div>
<p className="text-xs text-muted-foreground">
{(stats.errors_total ?? 0).toLocaleString()} total errors
</p>
<div className="text-2xl font-bold">{formatPercent((stats.error_rate ?? 0) * 100)}</div>
</CardContent>
</Card>
@@ -80,8 +74,8 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
<Gauge className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{(stats.requests_per_second ?? 0).toFixed(2)}</div>
<p className="text-xs text-muted-foreground">requests per second</p>
<div className="text-2xl font-bold">{(stats.requests_per_minute ?? 0).toFixed(2)}</div>
<p className="text-xs text-muted-foreground">requests per minute</p>
</CardContent>
</Card>
</div>
@@ -121,22 +115,22 @@ export function HTTPEndpointStats({ stats }: HTTPStatsProps) {
<TableHead>Endpoint</TableHead>
<TableHead className="text-right">Requests</TableHead>
<TableHead className="text-right">Avg Latency</TableHead>
<TableHead className="text-right">Errors</TableHead>
<TableHead className="text-right">P95 Latency</TableHead>
<TableHead className="text-right">Error Rate</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{sortedEndpoints.map(([endpoint, data]) => {
const errorRate = data.count > 0 ? (data.errors / data.count) * 100 : 0;
const errorRatePercent = (data.error_rate ?? 0) * 100;
return (
<TableRow key={endpoint}>
<TableCell className="font-mono text-sm">{endpoint}</TableCell>
<TableCell className="text-right">{data.count.toLocaleString()}</TableCell>
<TableCell className="text-right">{formatLatency(data.avg_latency_ms)}</TableCell>
<TableCell className="text-right">{data.errors}</TableCell>
<TableCell className="text-right">{formatLatency(data.p95_latency_ms)}</TableCell>
<TableCell className="text-right">
<span className={errorRate > 5 ? 'text-red-500' : ''}>
{formatPercent(errorRate)}
<span className={errorRatePercent > 5 ? 'text-red-500' : ''}>
{formatPercent(errorRatePercent)}
</span>
</TableCell>
</TableRow>

View File

@@ -18,7 +18,7 @@ interface QueueStatsProps {
}
export function QueueOverview({ stats }: QueueStatsProps) {
if (!stats) {
if (!stats || !stats.queues) {
return (
<Card>
<CardHeader>
@@ -33,6 +33,18 @@ export function QueueOverview({ stats }: QueueStatsProps) {
);
}
// Calculate totals from individual queues
const totals = Object.values(stats.queues).reduce(
(acc, queue) => ({
pending: acc.pending + (queue.pending ?? 0),
active: acc.active + (queue.active ?? 0),
scheduled: acc.scheduled + (queue.scheduled ?? 0),
retry: acc.retry + (queue.retry ?? 0),
failed: acc.failed + (queue.failed ?? 0),
}),
{ pending: 0, active: 0, scheduled: 0, retry: 0, failed: 0 }
);
return (
<div className="grid gap-4 md:grid-cols-5">
<Card>
@@ -41,7 +53,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
<Clock className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.total_pending}</div>
<div className="text-2xl font-bold">{totals.pending}</div>
<p className="text-xs text-muted-foreground">tasks waiting</p>
</CardContent>
</Card>
@@ -52,7 +64,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
<PlayCircle className="h-4 w-4 text-blue-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-blue-500">{stats.total_active}</div>
<div className="text-2xl font-bold text-blue-500">{totals.active}</div>
<p className="text-xs text-muted-foreground">currently running</p>
</CardContent>
</Card>
@@ -63,7 +75,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
<Clock className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.total_scheduled}</div>
<div className="text-2xl font-bold">{totals.scheduled}</div>
<p className="text-xs text-muted-foreground">future tasks</p>
</CardContent>
</Card>
@@ -74,7 +86,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
<RotateCcw className="h-4 w-4 text-yellow-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-yellow-500">{stats.total_retry}</div>
<div className="text-2xl font-bold text-yellow-500">{totals.retry}</div>
<p className="text-xs text-muted-foreground">awaiting retry</p>
</CardContent>
</Card>
@@ -85,7 +97,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
<AlertTriangle className="h-4 w-4 text-red-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-red-500">{stats.total_failed}</div>
<div className="text-2xl font-bold text-red-500">{totals.failed}</div>
<p className="text-xs text-muted-foreground">permanently failed</p>
</CardContent>
</Card>
@@ -143,7 +155,6 @@ export function QueueDetails({ stats }: QueueStatsProps) {
<TableHeader>
<TableRow>
<TableHead>Queue</TableHead>
<TableHead className="text-right">Size</TableHead>
<TableHead className="text-right">Pending</TableHead>
<TableHead className="text-right">Active</TableHead>
<TableHead className="text-right">Scheduled</TableHead>
@@ -157,26 +168,25 @@ export function QueueDetails({ stats }: QueueStatsProps) {
{sortedQueues.map(([queueName, queue]) => (
<TableRow key={queueName}>
<TableCell>{getPriorityBadge(queueName)}</TableCell>
<TableCell className="text-right">{queue.size}</TableCell>
<TableCell className="text-right">{queue.pending}</TableCell>
<TableCell className="text-right">{queue.pending ?? 0}</TableCell>
<TableCell className="text-right">
<span className={queue.active > 0 ? 'text-blue-500 font-medium' : ''}>
{queue.active}
<span className={(queue.active ?? 0) > 0 ? 'text-blue-500 font-medium' : ''}>
{queue.active ?? 0}
</span>
</TableCell>
<TableCell className="text-right">{queue.scheduled}</TableCell>
<TableCell className="text-right">{queue.scheduled ?? 0}</TableCell>
<TableCell className="text-right">
<span className={queue.retry > 0 ? 'text-yellow-500' : ''}>
{queue.retry}
<span className={(queue.retry ?? 0) > 0 ? 'text-yellow-500' : ''}>
{queue.retry ?? 0}
</span>
</TableCell>
<TableCell className="text-right">{queue.archived}</TableCell>
<TableCell className="text-right">{queue.archived ?? 0}</TableCell>
<TableCell className="text-right">
<span className="text-green-500">{queue.completed}</span>
<span className="text-green-500">{queue.completed ?? 0}</span>
</TableCell>
<TableCell className="text-right">
<span className={queue.failed > 0 ? 'text-red-500 font-medium' : ''}>
{queue.failed}
<span className={(queue.failed ?? 0) > 0 ? 'text-red-500 font-medium' : ''}>
{queue.failed ?? 0}
</span>
</TableCell>
</TableRow>

View File

@@ -35,9 +35,9 @@ function ProcessCard({ stats, title }: ProcessCardProps) {
<div className="space-y-1">
<div className="flex items-center gap-1 text-xs text-muted-foreground">
<Server className="h-3 w-3" />
Memory
Go Heap
</div>
<p className="text-lg font-semibold">{formatBytes(stats.memory?.go_alloc)}</p>
<p className="text-lg font-semibold">{formatBytes(stats.memory?.heap_alloc)}</p>
</div>
<div className="space-y-1">
<div className="flex items-center gap-1 text-xs text-muted-foreground">
@@ -122,9 +122,9 @@ export function SystemOverview({ apiStats, workerStats }: SystemOverviewProps) {
<Server className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{formatPercent(stats.memory?.system_percent)}</div>
<div className="text-2xl font-bold">{formatPercent(stats.memory?.usage_percent)}</div>
<p className="text-xs text-muted-foreground">
{formatBytes(stats.memory?.system_used)} / {formatBytes(stats.memory?.system_total)}
{formatBytes(stats.memory?.used_bytes)} / {formatBytes(stats.memory?.total_bytes)}
</p>
</CardContent>
</Card>
@@ -135,9 +135,9 @@ export function SystemOverview({ apiStats, workerStats }: SystemOverviewProps) {
<HardDrive className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{formatPercent(stats.disk?.percent)}</div>
<div className="text-2xl font-bold">{formatPercent(stats.disk?.usage_percent)}</div>
<p className="text-xs text-muted-foreground">
{formatBytes(stats.disk?.used)} / {formatBytes(stats.disk?.total)}
{formatBytes(stats.disk?.used_bytes)} / {formatBytes(stats.disk?.total_bytes)}
</p>
</CardContent>
</Card>
@@ -148,9 +148,9 @@ export function SystemOverview({ apiStats, workerStats }: SystemOverviewProps) {
<Zap className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{(apiStats?.runtime.gc_runs || 0) + (workerStats?.runtime.gc_runs || 0)}</div>
<div className="text-2xl font-bold">{(apiStats?.runtime?.num_gc || 0) + (workerStats?.runtime?.num_gc || 0)}</div>
<p className="text-xs text-muted-foreground">
Total pause: {((apiStats?.runtime.gc_pause_total_ns || 0) + (workerStats?.runtime.gc_pause_total_ns || 0)) / 1000000}ms
Last pause: {safeToFixed(((apiStats?.runtime?.last_gc_pause_ns || 0) + (workerStats?.runtime?.last_gc_pause_ns || 0)) / 1000000)}ms
</p>
</CardContent>
</Card>

View File

@@ -12,55 +12,54 @@ export interface LogEntry {
export interface CPUStats {
usage_percent: number;
num_cpu: number;
load_avg_1: number;
load_avg_5: number;
load_avg_15: number;
}
export interface MemoryStats {
system_total: number;
system_used: number;
system_percent: number;
go_alloc: number;
go_total_alloc: number;
go_sys: number;
go_heap_alloc: number;
go_heap_sys: number;
// System memory
used_bytes: number;
total_bytes: number;
usage_percent: number;
// Go heap
heap_alloc: number;
heap_sys: number;
heap_inuse: number;
}
export interface DiskStats {
total: number;
used: number;
percent: number;
used_bytes: number;
total_bytes: number;
free_bytes: number;
usage_percent: number;
}
export interface RuntimeStats {
goroutines: number;
gc_runs: number;
gc_pause_ns: number;
gc_pause_total_ns: number;
num_gc: number;
last_gc_pause_ns: number;
uptime_seconds: number;
}
export interface EndpointStats {
count: number;
total_latency_ms: number;
avg_latency_ms: number;
errors: number;
p95_latency_ms: number;
error_rate: number;
}
export interface HTTPStats {
total_requests: number;
requests_per_second: number;
requests_total: number;
requests_per_minute: number;
avg_latency_ms: number;
p95_latency_ms: number;
errors_total: number;
error_rate: number;
by_endpoint: Record<string, EndpointStats>;
by_status_code: Record<number, number>;
}
export interface QueueStats {
size: number;
pending: number;
active: number;
scheduled: number;
@@ -72,11 +71,6 @@ export interface QueueStats {
export interface AsynqStats {
queues: Record<string, QueueStats>;
total_pending: number;
total_active: number;
total_scheduled: number;
total_retry: number;
total_failed: number;
}
export interface SystemStats {