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:
@@ -41,9 +41,9 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
|
|||||||
<Activity className="h-4 w-4 text-muted-foreground" />
|
<Activity className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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">
|
<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>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -55,9 +55,6 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{formatLatency(stats.avg_latency_ms)}</div>
|
<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>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
@@ -67,10 +64,7 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
|
|||||||
<AlertTriangle className="h-4 w-4 text-muted-foreground" />
|
<AlertTriangle className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{formatPercent(stats.error_rate)}</div>
|
<div className="text-2xl font-bold">{formatPercent((stats.error_rate ?? 0) * 100)}</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
|
||||||
{(stats.errors_total ?? 0).toLocaleString()} total errors
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
@@ -80,8 +74,8 @@ export function HTTPStatsOverview({ stats }: HTTPStatsProps) {
|
|||||||
<Gauge className="h-4 w-4 text-muted-foreground" />
|
<Gauge className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">{(stats.requests_per_second ?? 0).toFixed(2)}</div>
|
<div className="text-2xl font-bold">{(stats.requests_per_minute ?? 0).toFixed(2)}</div>
|
||||||
<p className="text-xs text-muted-foreground">requests per second</p>
|
<p className="text-xs text-muted-foreground">requests per minute</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,22 +115,22 @@ export function HTTPEndpointStats({ stats }: HTTPStatsProps) {
|
|||||||
<TableHead>Endpoint</TableHead>
|
<TableHead>Endpoint</TableHead>
|
||||||
<TableHead className="text-right">Requests</TableHead>
|
<TableHead className="text-right">Requests</TableHead>
|
||||||
<TableHead className="text-right">Avg Latency</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>
|
<TableHead className="text-right">Error Rate</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{sortedEndpoints.map(([endpoint, data]) => {
|
{sortedEndpoints.map(([endpoint, data]) => {
|
||||||
const errorRate = data.count > 0 ? (data.errors / data.count) * 100 : 0;
|
const errorRatePercent = (data.error_rate ?? 0) * 100;
|
||||||
return (
|
return (
|
||||||
<TableRow key={endpoint}>
|
<TableRow key={endpoint}>
|
||||||
<TableCell className="font-mono text-sm">{endpoint}</TableCell>
|
<TableCell className="font-mono text-sm">{endpoint}</TableCell>
|
||||||
<TableCell className="text-right">{data.count.toLocaleString()}</TableCell>
|
<TableCell className="text-right">{data.count.toLocaleString()}</TableCell>
|
||||||
<TableCell className="text-right">{formatLatency(data.avg_latency_ms)}</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">
|
<TableCell className="text-right">
|
||||||
<span className={errorRate > 5 ? 'text-red-500' : ''}>
|
<span className={errorRatePercent > 5 ? 'text-red-500' : ''}>
|
||||||
{formatPercent(errorRate)}
|
{formatPercent(errorRatePercent)}
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ interface QueueStatsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function QueueOverview({ stats }: QueueStatsProps) {
|
export function QueueOverview({ stats }: QueueStatsProps) {
|
||||||
if (!stats) {
|
if (!stats || !stats.queues) {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<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 (
|
return (
|
||||||
<div className="grid gap-4 md:grid-cols-5">
|
<div className="grid gap-4 md:grid-cols-5">
|
||||||
<Card>
|
<Card>
|
||||||
@@ -41,7 +53,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
|
|||||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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>
|
<p className="text-xs text-muted-foreground">tasks waiting</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -52,7 +64,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
|
|||||||
<PlayCircle className="h-4 w-4 text-blue-500" />
|
<PlayCircle className="h-4 w-4 text-blue-500" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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>
|
<p className="text-xs text-muted-foreground">currently running</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -63,7 +75,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
|
|||||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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>
|
<p className="text-xs text-muted-foreground">future tasks</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -74,7 +86,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
|
|||||||
<RotateCcw className="h-4 w-4 text-yellow-500" />
|
<RotateCcw className="h-4 w-4 text-yellow-500" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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>
|
<p className="text-xs text-muted-foreground">awaiting retry</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -85,7 +97,7 @@ export function QueueOverview({ stats }: QueueStatsProps) {
|
|||||||
<AlertTriangle className="h-4 w-4 text-red-500" />
|
<AlertTriangle className="h-4 w-4 text-red-500" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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>
|
<p className="text-xs text-muted-foreground">permanently failed</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -143,7 +155,6 @@ export function QueueDetails({ stats }: QueueStatsProps) {
|
|||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Queue</TableHead>
|
<TableHead>Queue</TableHead>
|
||||||
<TableHead className="text-right">Size</TableHead>
|
|
||||||
<TableHead className="text-right">Pending</TableHead>
|
<TableHead className="text-right">Pending</TableHead>
|
||||||
<TableHead className="text-right">Active</TableHead>
|
<TableHead className="text-right">Active</TableHead>
|
||||||
<TableHead className="text-right">Scheduled</TableHead>
|
<TableHead className="text-right">Scheduled</TableHead>
|
||||||
@@ -157,26 +168,25 @@ export function QueueDetails({ stats }: QueueStatsProps) {
|
|||||||
{sortedQueues.map(([queueName, queue]) => (
|
{sortedQueues.map(([queueName, queue]) => (
|
||||||
<TableRow key={queueName}>
|
<TableRow key={queueName}>
|
||||||
<TableCell>{getPriorityBadge(queueName)}</TableCell>
|
<TableCell>{getPriorityBadge(queueName)}</TableCell>
|
||||||
<TableCell className="text-right">{queue.size}</TableCell>
|
<TableCell className="text-right">{queue.pending ?? 0}</TableCell>
|
||||||
<TableCell className="text-right">{queue.pending}</TableCell>
|
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<span className={queue.active > 0 ? 'text-blue-500 font-medium' : ''}>
|
<span className={(queue.active ?? 0) > 0 ? 'text-blue-500 font-medium' : ''}>
|
||||||
{queue.active}
|
{queue.active ?? 0}
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right">{queue.scheduled}</TableCell>
|
<TableCell className="text-right">{queue.scheduled ?? 0}</TableCell>
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<span className={queue.retry > 0 ? 'text-yellow-500' : ''}>
|
<span className={(queue.retry ?? 0) > 0 ? 'text-yellow-500' : ''}>
|
||||||
{queue.retry}
|
{queue.retry ?? 0}
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right">{queue.archived}</TableCell>
|
<TableCell className="text-right">{queue.archived ?? 0}</TableCell>
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<span className="text-green-500">{queue.completed}</span>
|
<span className="text-green-500">{queue.completed ?? 0}</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
<span className={queue.failed > 0 ? 'text-red-500 font-medium' : ''}>
|
<span className={(queue.failed ?? 0) > 0 ? 'text-red-500 font-medium' : ''}>
|
||||||
{queue.failed}
|
{queue.failed ?? 0}
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ function ProcessCard({ stats, title }: ProcessCardProps) {
|
|||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||||
<Server className="h-3 w-3" />
|
<Server className="h-3 w-3" />
|
||||||
Memory
|
Go Heap
|
||||||
</div>
|
</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>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
<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" />
|
<Server className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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">
|
<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>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -135,9 +135,9 @@ export function SystemOverview({ apiStats, workerStats }: SystemOverviewProps) {
|
|||||||
<HardDrive className="h-4 w-4 text-muted-foreground" />
|
<HardDrive className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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">
|
<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>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -148,9 +148,9 @@ export function SystemOverview({ apiStats, workerStats }: SystemOverviewProps) {
|
|||||||
<Zap className="h-4 w-4 text-muted-foreground" />
|
<Zap className="h-4 w-4 text-muted-foreground" />
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<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">
|
<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>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -12,55 +12,54 @@ export interface LogEntry {
|
|||||||
|
|
||||||
export interface CPUStats {
|
export interface CPUStats {
|
||||||
usage_percent: number;
|
usage_percent: number;
|
||||||
|
num_cpu: number;
|
||||||
load_avg_1: number;
|
load_avg_1: number;
|
||||||
load_avg_5: number;
|
load_avg_5: number;
|
||||||
load_avg_15: number;
|
load_avg_15: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MemoryStats {
|
export interface MemoryStats {
|
||||||
system_total: number;
|
// System memory
|
||||||
system_used: number;
|
used_bytes: number;
|
||||||
system_percent: number;
|
total_bytes: number;
|
||||||
go_alloc: number;
|
usage_percent: number;
|
||||||
go_total_alloc: number;
|
// Go heap
|
||||||
go_sys: number;
|
heap_alloc: number;
|
||||||
go_heap_alloc: number;
|
heap_sys: number;
|
||||||
go_heap_sys: number;
|
heap_inuse: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DiskStats {
|
export interface DiskStats {
|
||||||
total: number;
|
used_bytes: number;
|
||||||
used: number;
|
total_bytes: number;
|
||||||
percent: number;
|
free_bytes: number;
|
||||||
|
usage_percent: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RuntimeStats {
|
export interface RuntimeStats {
|
||||||
goroutines: number;
|
goroutines: number;
|
||||||
gc_runs: number;
|
num_gc: number;
|
||||||
gc_pause_ns: number;
|
last_gc_pause_ns: number;
|
||||||
gc_pause_total_ns: number;
|
|
||||||
uptime_seconds: number;
|
uptime_seconds: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EndpointStats {
|
export interface EndpointStats {
|
||||||
count: number;
|
count: number;
|
||||||
total_latency_ms: number;
|
|
||||||
avg_latency_ms: number;
|
avg_latency_ms: number;
|
||||||
errors: number;
|
p95_latency_ms: number;
|
||||||
|
error_rate: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HTTPStats {
|
export interface HTTPStats {
|
||||||
total_requests: number;
|
requests_total: number;
|
||||||
requests_per_second: number;
|
requests_per_minute: number;
|
||||||
avg_latency_ms: number;
|
avg_latency_ms: number;
|
||||||
p95_latency_ms: number;
|
|
||||||
errors_total: number;
|
|
||||||
error_rate: number;
|
error_rate: number;
|
||||||
by_endpoint: Record<string, EndpointStats>;
|
by_endpoint: Record<string, EndpointStats>;
|
||||||
|
by_status_code: Record<number, number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueueStats {
|
export interface QueueStats {
|
||||||
size: number;
|
|
||||||
pending: number;
|
pending: number;
|
||||||
active: number;
|
active: number;
|
||||||
scheduled: number;
|
scheduled: number;
|
||||||
@@ -72,11 +71,6 @@ export interface QueueStats {
|
|||||||
|
|
||||||
export interface AsynqStats {
|
export interface AsynqStats {
|
||||||
queues: Record<string, QueueStats>;
|
queues: Record<string, QueueStats>;
|
||||||
total_pending: number;
|
|
||||||
total_active: number;
|
|
||||||
total_scheduled: number;
|
|
||||||
total_retry: number;
|
|
||||||
total_failed: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SystemStats {
|
export interface SystemStats {
|
||||||
|
|||||||
Reference in New Issue
Block a user