Spaces:
Sleeping
Sleeping
File size: 4,599 Bytes
2857363 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import { BarChart3, Zap, Database, HardDrive, RefreshCw, TrendingUp } from 'lucide-react';
import { useCacheStats } from '../hooks/useCacheStats';
import { formatMemory } from '../utils/formatters';
const CacheStats = () => {
const { stats, isLoading, error, refresh } = useCacheStats(30000);
if (error) {
return (
<div className="bg-white rounded-xl border border-gray-200 p-6">
<div className="text-center py-4">
<p className="text-red-500 text-sm mb-2">{error}</p>
<button
onClick={refresh}
className="text-sm text-blue-600 hover:underline"
>
Retry
</button>
</div>
</div>
);
}
const hitRate = stats?.hit_rate ?? 0;
const hitRateColor = hitRate >= 80 ? 'text-green-600' : hitRate >= 50 ? 'text-yellow-600' : 'text-red-600';
const hitRateBg = hitRate >= 80 ? 'bg-green-500' : hitRate >= 50 ? 'bg-yellow-500' : 'bg-red-500';
return (
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-gray-100">
<div className="flex items-center gap-2">
<BarChart3 className="w-5 h-5 text-gray-500" />
<h3 className="font-semibold text-gray-900">Cache Performance</h3>
</div>
<button
onClick={refresh}
disabled={isLoading}
className="p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors disabled:opacity-50"
aria-label="Refresh stats"
>
<RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
</button>
</div>
{/* Stats Grid */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 p-4">
{/* Total Analyses */}
<StatCard
icon={<Database className="w-5 h-5 text-blue-500" />}
label="Total Keys"
value={stats?.total_keys?.toLocaleString() ?? '-'}
isLoading={isLoading}
/>
{/* Cache Hit Rate */}
<StatCard
icon={<Zap className="w-5 h-5 text-yellow-500" />}
label="Hit Rate"
value={stats ? `${hitRate.toFixed(1)}%` : '-'}
valueClass={hitRateColor}
isLoading={isLoading}
>
{stats && (
<div className="mt-2 h-1.5 bg-gray-200 rounded-full overflow-hidden">
<div
className={`h-full rounded-full transition-all duration-500 ${hitRateBg}`}
style={{ width: `${hitRate}%` }}
/>
</div>
)}
</StatCard>
{/* Hits vs Misses */}
<StatCard
icon={<TrendingUp className="w-5 h-5 text-green-500" />}
label="Hits / Misses"
value={stats ? `${stats.hits} / ${stats.misses}` : '-'}
isLoading={isLoading}
/>
{/* Memory Used */}
<StatCard
icon={<HardDrive className="w-5 h-5 text-purple-500" />}
label="Memory Used"
value={stats ? formatMemory(stats.memory_used_mb) : '-'}
isLoading={isLoading}
/>
</div>
{/* Status Indicator */}
{stats && (
<div className="px-4 pb-4">
<div className="flex items-center gap-2 text-xs text-gray-500">
<span
className={`w-2 h-2 rounded-full ${
stats.status === 'connected' ? 'bg-green-500' : 'bg-red-500'
}`}
/>
<span>
Redis {stats.status === 'connected' ? 'Connected' : 'Disconnected'}
</span>
<span className="text-gray-300">•</span>
<span>Auto-refreshes every 30s</span>
</div>
</div>
)}
</div>
);
};
interface StatCardProps {
icon: React.ReactNode;
label: string;
value: string;
valueClass?: string;
isLoading?: boolean;
children?: React.ReactNode;
}
const StatCard = ({ icon, label, value, valueClass = '', isLoading, children }: StatCardProps) => {
return (
<div className="p-4 bg-gray-50 rounded-lg">
<div className="flex items-center gap-2 mb-2">
{icon}
<span className="text-sm text-gray-600">{label}</span>
</div>
{isLoading ? (
<div className="h-8 bg-gray-200 rounded animate-pulse" />
) : (
<>
<p className={`text-2xl font-bold font-mono ${valueClass || 'text-gray-900'}`}>
{value}
</p>
{children}
</>
)}
</div>
);
};
export default CacheStats;
|