🚀 Initial commit: Versão atual do TrackSteel APP

This commit is contained in:
2026-03-18 21:17:53 +00:00
commit bde410c9ad
633 changed files with 108150 additions and 0 deletions
+322
View File
@@ -0,0 +1,322 @@
/**
* Sistema de Monitoramento de Performance
* Rastreia métricas de performance e operações do sistema
*/
export interface PerformanceMetrics {
operation: string;
duration_ms: number;
cache_hit: boolean;
items_count: number;
query_count: number;
timestamp: Date;
metadata?: Record<string, any>;
}
export interface PerformanceTracker {
startTime: number;
operation: string;
metadata: Record<string, any>;
}
export interface SystemHealth {
cache_status: 'healthy' | 'degraded' | 'failed';
database_status: 'healthy' | 'slow' | 'failed';
average_response_time: number;
cache_hit_rate: number;
active_users: number;
timestamp: Date;
}
export class PerformanceMonitor {
private static trackers = new Map<string, PerformanceTracker>();
private static metrics: PerformanceMetrics[] = [];
private static readonly MAX_METRICS = 1000;
/**
* Inicia o rastreamento de uma operação
*/
static start(operation: string, metadata: Record<string, any> = {}): string {
const trackerId = `${operation}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.trackers.set(trackerId, {
startTime: performance.now(),
operation,
metadata
});
return trackerId;
}
/**
* Finaliza o rastreamento e retorna as métricas
*/
static end(trackerId: string): PerformanceMetrics | null {
const tracker = this.trackers.get(trackerId);
if (!tracker) {
console.warn(`Tracker não encontrado: ${trackerId}`);
return null;
}
const duration = performance.now() - tracker.startTime;
this.trackers.delete(trackerId);
const metrics: PerformanceMetrics = {
operation: tracker.operation,
duration_ms: Math.round(duration * 100) / 100, // 2 casas decimais
cache_hit: tracker.metadata.cache_hit || false,
items_count: tracker.metadata.items_count || 0,
query_count: tracker.metadata.query_count || 1,
timestamp: new Date(),
metadata: tracker.metadata
};
// Armazenar métricas
this.addMetrics(metrics);
// Log para desenvolvimento
if (process.env.NODE_ENV === 'development') {
this.logMetrics(metrics);
}
// Alertas para performance ruim
this.checkPerformanceAlerts(metrics);
return metrics;
}
/**
* Adiciona métricas ao histórico
*/
private static addMetrics(metrics: PerformanceMetrics): void {
this.metrics.push(metrics);
// Manter apenas as últimas métricas
if (this.metrics.length > this.MAX_METRICS) {
this.metrics.splice(0, this.metrics.length - this.MAX_METRICS);
}
// Persistir no localStorage para análise
try {
const persistedMetrics = this.metrics.slice(-100); // Últimas 100
localStorage.setItem('performance_metrics', JSON.stringify(persistedMetrics));
} catch (error) {
// Falha ao persistir não é crítica
}
}
/**
* Log formatado das métricas
*/
private static logMetrics(metrics: PerformanceMetrics): void {
const emoji = metrics.cache_hit ? '⚡' : '🔍';
const color = metrics.duration_ms > 1000 ? 'color: red' :
metrics.duration_ms > 500 ? 'color: orange' : 'color: green';
console.log(
`%c${emoji} ${metrics.operation}`,
color,
`${metrics.duration_ms}ms`,
metrics.cache_hit ? '(cache)' : '(fresh)',
metrics.items_count > 0 ? `${metrics.items_count} items` : ''
);
}
/**
* Verifica alertas de performance
*/
private static checkPerformanceAlerts(metrics: PerformanceMetrics): void {
// Alerta para operações muito lentas
if (metrics.duration_ms > 2000) {
console.warn(`⚠️ Operação lenta detectada: ${metrics.operation} (${metrics.duration_ms}ms)`);
}
// Alerta para baixa taxa de cache hit
const recentMetrics = this.metrics.slice(-20);
const cacheHitRate = recentMetrics.filter(m => m.cache_hit).length / recentMetrics.length;
if (recentMetrics.length >= 10 && cacheHitRate < 0.3) {
console.warn(`⚠️ Taxa de cache hit baixa: ${Math.round(cacheHitRate * 100)}%`);
}
}
/**
* Obtém estatísticas de performance
*/
static getStats(): {
totalOperations: number;
averageResponseTime: number;
cacheHitRate: number;
slowOperations: number;
operationsByType: Record<string, number>;
} {
if (this.metrics.length === 0) {
return {
totalOperations: 0,
averageResponseTime: 0,
cacheHitRate: 0,
slowOperations: 0,
operationsByType: {}
};
}
const totalOperations = this.metrics.length;
const averageResponseTime = this.metrics.reduce((sum, m) => sum + m.duration_ms, 0) / totalOperations;
const cacheHitRate = this.metrics.filter(m => m.cache_hit).length / totalOperations;
const slowOperations = this.metrics.filter(m => m.duration_ms > 1000).length;
const operationsByType = this.metrics.reduce((acc, m) => {
acc[m.operation] = (acc[m.operation] || 0) + 1;
return acc;
}, {} as Record<string, number>);
return {
totalOperations,
averageResponseTime: Math.round(averageResponseTime * 100) / 100,
cacheHitRate: Math.round(cacheHitRate * 100) / 100,
slowOperations,
operationsByType
};
}
/**
* Obtém métricas recentes
*/
static getRecentMetrics(limit: number = 50): PerformanceMetrics[] {
return this.metrics.slice(-limit);
}
/**
* Limpa todas as métricas
*/
static clearMetrics(): void {
this.metrics = [];
this.trackers.clear();
localStorage.removeItem('performance_metrics');
}
/**
* Carrega métricas persistidas
*/
static loadPersistedMetrics(): void {
try {
const stored = localStorage.getItem('performance_metrics');
if (stored) {
const parsed = JSON.parse(stored);
this.metrics = parsed.map((m: any) => ({
...m,
timestamp: new Date(m.timestamp)
}));
}
} catch (error) {
console.warn('Erro ao carregar métricas persistidas:', error);
}
}
}
/**
* Hook para monitoramento automático de performance
*/
export const usePerformanceTracking = (
operation: string,
dependencies: any[] = [],
metadata: Record<string, any> = {}
) => {
const [metrics, setMetrics] = React.useState<PerformanceMetrics | null>(null);
const trackerRef = React.useRef<string | null>(null);
React.useEffect(() => {
// Iniciar rastreamento
trackerRef.current = PerformanceMonitor.start(operation, metadata);
return () => {
// Finalizar rastreamento
if (trackerRef.current) {
const result = PerformanceMonitor.end(trackerRef.current);
setMetrics(result);
trackerRef.current = null;
}
};
}, dependencies);
return metrics;
};
/**
* Hook para monitoramento de saúde do sistema
*/
export const useSystemHealth = () => {
const [health, setHealth] = React.useState<SystemHealth | null>(null);
const [loading, setLoading] = React.useState(false);
const checkHealth = React.useCallback(async (): Promise<SystemHealth> => {
const startTime = performance.now();
try {
// Simular verificação de conectividade (adaptar conforme necessário)
const response = await fetch('/api/health', {
method: 'HEAD',
cache: 'no-cache'
}).catch(() => null);
const dbResponseTime = performance.now() - startTime;
// Verificar status do cache
const cacheStats = OptimizedCache.getStats();
const cacheStatus = cacheStats.localStorageEntries > 0 ? 'healthy' : 'degraded';
// Calcular taxa de cache hit
const performanceStats = PerformanceMonitor.getStats();
const health: SystemHealth = {
cache_status: cacheStatus,
database_status: !response ? 'failed' :
dbResponseTime > 2000 ? 'slow' : 'healthy',
average_response_time: Math.round(dbResponseTime),
cache_hit_rate: performanceStats.cacheHitRate,
active_users: 1, // Implementar contagem real se necessário
timestamp: new Date()
};
return health;
} catch (error) {
return {
cache_status: 'failed',
database_status: 'failed',
average_response_time: -1,
cache_hit_rate: 0,
active_users: 0,
timestamp: new Date()
};
}
}, []);
React.useEffect(() => {
const performCheck = async () => {
setLoading(true);
try {
const healthData = await checkHealth();
setHealth(healthData);
} catch (error) {
console.error('Erro ao verificar saúde do sistema:', error);
} finally {
setLoading(false);
}
};
performCheck();
// Verificar a cada 30 segundos
const interval = setInterval(performCheck, 30000);
return () => clearInterval(interval);
}, [checkHealth]);
return { health, loading, refetch: checkHealth };
};
// Importações necessárias
import React from 'react';
import { OptimizedCache } from './OptimizedCache';
// Inicializar métricas persistidas ao carregar o módulo
PerformanceMonitor.loadPersistedMetrics();
export default PerformanceMonitor;