93 lines
3.1 KiB
TypeScript
93 lines
3.1 KiB
TypeScript
'use client';
|
|
|
|
import { formatPercent, formatBytesPerSec } from '@/lib/formatters';
|
|
import type { MetricInstance, NetworkMetrics } from '@/types/metrics';
|
|
|
|
interface SummaryCardsProps {
|
|
cpu: MetricInstance[];
|
|
memory: MetricInstance[];
|
|
disk: MetricInstance[];
|
|
ingress: NetworkMetrics;
|
|
istio: NetworkMetrics;
|
|
}
|
|
|
|
interface CardData {
|
|
label: string;
|
|
avg: string;
|
|
max: string;
|
|
min: string;
|
|
color: string;
|
|
}
|
|
|
|
function getClusterStats(instances: MetricInstance[]): { avg: number; max: number; min: number } {
|
|
if (instances.length === 0) return { avg: 0, max: 0, min: 0 };
|
|
const avg = instances.reduce((sum, i) => sum + i.stats.avg, 0) / instances.length;
|
|
const max = Math.max(...instances.map((i) => i.stats.max));
|
|
const min = Math.min(...instances.map((i) => i.stats.min));
|
|
return { avg, max, min };
|
|
}
|
|
|
|
export default function SummaryCards({ cpu, memory, disk, ingress, istio }: SummaryCardsProps) {
|
|
const cpuStats = getClusterStats(cpu);
|
|
const memStats = getClusterStats(memory);
|
|
const diskStats = getClusterStats(disk);
|
|
|
|
const ingressRxAvg = ingress.receive.reduce((sum, i) => sum + i.stats.avg, 0);
|
|
const ingressTxAvg = ingress.transmit.reduce((sum, i) => sum + i.stats.avg, 0);
|
|
const istioRxAvg = istio.receive.reduce((sum, i) => sum + i.stats.avg, 0);
|
|
const istioTxAvg = istio.transmit.reduce((sum, i) => sum + i.stats.avg, 0);
|
|
|
|
const cards: CardData[] = [
|
|
{
|
|
label: 'CPU',
|
|
avg: formatPercent(cpuStats.avg),
|
|
max: formatPercent(cpuStats.max),
|
|
min: formatPercent(cpuStats.min),
|
|
color: cpuStats.max > 90 ? 'border-red-500' : cpuStats.max > 70 ? 'border-yellow-500' : 'border-green-500',
|
|
},
|
|
{
|
|
label: 'Memory',
|
|
avg: formatPercent(memStats.avg),
|
|
max: formatPercent(memStats.max),
|
|
min: formatPercent(memStats.min),
|
|
color: memStats.max > 90 ? 'border-red-500' : memStats.max > 70 ? 'border-yellow-500' : 'border-green-500',
|
|
},
|
|
{
|
|
label: 'Disk',
|
|
avg: formatPercent(diskStats.avg),
|
|
max: formatPercent(diskStats.max),
|
|
min: formatPercent(diskStats.min),
|
|
color: diskStats.max > 90 ? 'border-red-500' : diskStats.max > 70 ? 'border-yellow-500' : 'border-green-500',
|
|
},
|
|
{
|
|
label: 'Ingress',
|
|
avg: `RX ${formatBytesPerSec(ingressRxAvg)}`,
|
|
max: `TX ${formatBytesPerSec(ingressTxAvg)}`,
|
|
min: '',
|
|
color: 'border-blue-500',
|
|
},
|
|
{
|
|
label: 'Istio',
|
|
avg: `RX ${formatBytesPerSec(istioRxAvg)}`,
|
|
max: `TX ${formatBytesPerSec(istioTxAvg)}`,
|
|
min: '',
|
|
color: 'border-purple-500',
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="grid grid-cols-2 lg:grid-cols-5 gap-4">
|
|
{cards.map((card) => (
|
|
<div key={card.label} className={`bg-white rounded-lg shadow p-4 border-l-4 ${card.color}`}>
|
|
<h3 className="text-sm font-medium text-gray-500">{card.label}</h3>
|
|
<div className="mt-2 space-y-1">
|
|
<p className="text-lg font-semibold">avg: {card.avg}</p>
|
|
<p className="text-sm text-gray-600">max: {card.max}</p>
|
|
{card.min && <p className="text-sm text-gray-600">min: {card.min}</p>}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|