Loto / src /components /PerformanceMonitor.tsx
Raí Santos
oi
4c1e4ec
import React, { useState, useEffect } from 'react';
import { Activity, Zap, Shield, Package, Clock, TrendingUp } from 'lucide-react';
import { usePerformanceAnalyzer } from '../utils/PerformanceAnalyzer';
import { bundleOptimizer } from '../utils/BundleOptimizerAdvanced';
import { securityEnhanced } from '../utils/SecurityEnhanced';
export const PerformanceMonitor: React.FC = () => {
const { getReport } = usePerformanceAnalyzer();
const [performanceData, setPerformanceData] = useState<any>(null);
const [bundleData, setBundleData] = useState<any>(null);
const [securityData, setSecurityData] = useState<any>(null);
useEffect(() => {
let mounted = true; // Flag para evitar vazamento de memória
const updateData = () => {
if (!mounted) return; // Não atualizar se componente foi desmontado
try {
setPerformanceData(getReport());
setBundleData(bundleOptimizer.getOptimizationReport());
setSecurityData(securityEnhanced.getSecurityReport());
} catch (error) {
console.warn('Erro ao atualizar dados de performance:', error);
}
};
updateData();
const interval = setInterval(updateData, 5000); // Update every 5 seconds
return () => {
mounted = false; // Marcar como desmontado
clearInterval(interval);
};
}, [getReport]);
if (!performanceData || !bundleData || !securityData) {
return (
<div className="p-6 bg-white rounded-lg shadow-lg">
<div className="animate-pulse">
<div className="h-4 bg-gray-200 rounded w-1/4 mb-4"></div>
<div className="h-3 bg-gray-200 rounded w-1/2 mb-2"></div>
<div className="h-3 bg-gray-200 rounded w-3/4"></div>
</div>
</div>
);
}
const formatBytes = (bytes: number) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const formatMs = (ms: number) => `${ms.toFixed(1)}ms`;
return (
<div className="space-y-6">
{/* Header */}
<div className="bg-gradient-to-r from-blue-500 to-purple-600 text-white p-6 rounded-lg">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Activity className="w-6 h-6" />
Monitor de Performance
</h2>
<p className="text-blue-100 mt-2">
Monitoramento em tempo real da performance, bundle e segurança
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Performance Metrics */}
<div className="bg-white p-6 rounded-lg shadow-lg">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<Zap className="w-5 h-5 text-yellow-500" />
Performance
</h3>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-sm text-gray-600">Tempo de Carregamento:</span>
<span className="font-semibold">{formatMs(performanceData.metrics.loadTime)}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Tempo de Renderização:</span>
<span className="font-semibold">{formatMs(performanceData.metrics.renderTime)}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Uso de Memória:</span>
<span className="font-semibold">{formatBytes(performanceData.metrics.memoryUsage)}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Requisições de Rede:</span>
<span className="font-semibold">{performanceData.metrics.networkRequests}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Taxa de Cache:</span>
<span className="font-semibold text-green-600">
{performanceData.metrics.cacheHitRate.toFixed(1)}%
</span>
</div>
</div>
</div>
{/* Bundle Optimization */}
<div className="bg-white p-6 rounded-lg shadow-lg">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<Package className="w-5 h-5 text-blue-500" />
Bundle
</h3>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-sm text-gray-600">Tamanho Original:</span>
<span className="font-semibold">{formatBytes(bundleData.originalSize)}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Tamanho Otimizado:</span>
<span className="font-semibold text-green-600">{formatBytes(bundleData.optimizedSize)}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Economia:</span>
<span className="font-semibold text-green-600">{formatBytes(bundleData.savings)}</span>
</div>
<div className="bg-gray-200 rounded-full h-2 mt-3">
<div
className="bg-green-500 h-2 rounded-full transition-all duration-300"
style={{
width: `${((bundleData.savings / bundleData.originalSize) * 100).toFixed(1)}%`
}}
></div>
</div>
<p className="text-xs text-gray-600 text-center">
{((bundleData.savings / bundleData.originalSize) * 100).toFixed(1)}% de redução
</p>
</div>
</div>
{/* Security Status */}
<div className="bg-white p-6 rounded-lg shadow-lg">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<Shield className="w-5 h-5 text-green-500" />
Segurança
</h3>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-sm text-gray-600">Ameaças Detectadas:</span>
<span className={`font-semibold ${securityData.threatsDetected > 0 ? 'text-red-600' : 'text-green-600'}`}>
{securityData.threatsDetected}
</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Ameaças Mitigadas:</span>
<span className="font-semibold text-green-600">{securityData.threatsMitigated}</span>
</div>
<div className="flex justify-between">
<span className="text-sm text-gray-600">Últimas 24h:</span>
<span className="font-semibold">{securityData.recentThreats.length}</span>
</div>
<div className={`p-2 rounded-md text-center text-sm font-semibold ${
securityData.threatsDetected === 0
? 'bg-green-100 text-green-800'
: 'bg-yellow-100 text-yellow-800'
}`}>
{securityData.threatsDetected === 0 ? '✅ Sistema Seguro' : '⚠️ Monitorando'}
</div>
</div>
</div>
</div>
{/* Recommendations */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Performance Recommendations */}
<div className="bg-white p-6 rounded-lg shadow-lg">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<TrendingUp className="w-5 h-5 text-green-500" />
Recomendações de Performance
</h3>
<div className="space-y-2">
{performanceData.recommendations.map((recommendation: string, index: number) => (
<div key={index} className="p-3 bg-gray-50 rounded-md text-sm">
{recommendation}
</div>
))}
</div>
</div>
{/* Bundle Recommendations */}
<div className="bg-white p-6 rounded-lg shadow-lg">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<Package className="w-5 h-5 text-blue-500" />
Recomendações de Bundle
</h3>
<div className="space-y-2">
{bundleData.recommendations.map((recommendation: string, index: number) => (
<div key={index} className="p-3 bg-gray-50 rounded-md text-sm">
{recommendation}
</div>
))}
</div>
</div>
</div>
{/* Component Performance */}
{performanceData.components.length > 0 && (
<div className="bg-white p-6 rounded-lg shadow-lg">
<h3 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<Clock className="w-5 h-5 text-purple-500" />
Performance de Componentes
</h3>
<div className="overflow-x-auto">
<table className="min-w-full table-auto">
<thead>
<tr className="bg-gray-50">
<th className="px-4 py-2 text-left text-sm font-semibold text-gray-600">Componente</th>
<th className="px-4 py-2 text-left text-sm font-semibold text-gray-600">Renders</th>
<th className="px-4 py-2 text-left text-sm font-semibold text-gray-600">Tempo Total</th>
<th className="px-4 py-2 text-left text-sm font-semibold text-gray-600">Tempo Médio</th>
<th className="px-4 py-2 text-left text-sm font-semibold text-gray-600">Status</th>
</tr>
</thead>
<tbody>
{performanceData.components.slice(0, 10).map((component: any, index: number) => {
const avgTime = component.renderTime / component.renderCount;
const status = avgTime > 16 ? 'slow' : avgTime > 8 ? 'medium' : 'fast';
return (
<tr key={index} className="border-t">
<td className="px-4 py-2 text-sm text-gray-800">{component.name}</td>
<td className="px-4 py-2 text-sm text-gray-600">{component.renderCount}</td>
<td className="px-4 py-2 text-sm text-gray-600">{formatMs(component.renderTime)}</td>
<td className="px-4 py-2 text-sm text-gray-600">{formatMs(avgTime)}</td>
<td className="px-4 py-2">
<span className={`px-2 py-1 rounded-full text-xs font-semibold ${
status === 'fast' ? 'bg-green-100 text-green-800' :
status === 'medium' ? 'bg-yellow-100 text-yellow-800' :
'bg-red-100 text-red-800'
}`}>
{status === 'fast' ? '🚀 Rápido' :
status === 'medium' ? '⚡ Médio' : '🐌 Lento'}
</span>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
)}
</div>
);
};
export default PerformanceMonitor;