import { useState, useEffect, useRef, useCallback } from 'react'; import { logger } from '../utils/logger'; export interface SystemMetrics { memoryUsage: number; cpuUsage: number; networkLatency: number; apiResponseTime: number; websocketStatus: 'connected' | 'disconnected' | 'connecting'; dataQuality: { totalRecords: number; validRecords: number; invalidRecords: number; qualityScore: number; }; sensorStatus: { totalSensors: number; activeSensors: number; inactiveSensors: number; lastUpdate: string; }; } export interface PerformanceMetrics { componentRenderTime: number; apiCallTime: number; dataProcessingTime: number; } export const useMonitoring = () => { const [metrics, setMetrics] = useState({ memoryUsage: 0, cpuUsage: 0, networkLatency: 0, apiResponseTime: 0, websocketStatus: 'disconnected', dataQuality: { totalRecords: 0, validRecords: 0, invalidRecords: 0, qualityScore: 0 }, sensorStatus: { totalSensors: 0, activeSensors: 0, inactiveSensors: 0, lastUpdate: new Date().toISOString() } }); const [performanceMetrics, setPerformanceMetrics] = useState({ componentRenderTime: 0, apiCallTime: 0, dataProcessingTime: 0 }); const intervalRef = useRef(null); const apiCallTimes = useRef([]); const renderTimes = useRef([]); // 메모리 사용량 측정 const measureMemoryUsage = useCallback(() => { if ('memory' in performance) { const memory = (performance as any).memory; const usage = (memory.usedJSHeapSize / memory.totalJSHeapSize) * 100; return Math.round(usage * 100) / 100; } return 0; }, []); // 네트워크 지연 시간 측정 const measureNetworkLatency = useCallback(async () => { const start = performance.now(); try { await fetch('/api/health', { method: 'GET' }); const end = performance.now(); return end - start; } catch (error) { logger.warn('Network latency measurement failed', { error }); return 0; } }, []); // 데이터 품질 평가 const evaluateDataQuality = useCallback((data: any[]) => { if (data.length === 0) { return { totalRecords: 0, validRecords: 0, invalidRecords: 0, qualityScore: 0 }; } const validRecords = data.filter(item => { return item && typeof item.temperature === 'number' && typeof item.humidity === 'number' && !isNaN(item.temperature) && !isNaN(item.humidity); }).length; const invalidRecords = data.length - validRecords; const qualityScore = (validRecords / data.length) * 100; return { totalRecords: data.length, validRecords, invalidRecords, qualityScore: Math.round(qualityScore * 100) / 100 }; }, []); // 센서 상태 업데이트 const updateSensorStatus = useCallback((devices: any[]) => { const activeSensors = devices.filter(d => d.status === 'active').length; const totalSensors = devices.length; const inactiveSensors = totalSensors - activeSensors; return { totalSensors, activeSensors, inactiveSensors, lastUpdate: new Date().toISOString() }; }, []); // 성능 메트릭 업데이트 const updatePerformanceMetrics = useCallback(() => { if (apiCallTimes.current.length > 0) { const avgApiCallTime = apiCallTimes.current.reduce((a, b) => a + b, 0) / apiCallTimes.current.length; setPerformanceMetrics(prev => ({ ...prev, apiCallTime: Math.round(avgApiCallTime * 100) / 100 })); } if (renderTimes.current.length > 0) { const avgRenderTime = renderTimes.current.reduce((a, b) => a + b, 0) / renderTimes.current.length; setPerformanceMetrics(prev => ({ ...prev, componentRenderTime: Math.round(avgRenderTime * 100) / 100 })); } }, []); // 메트릭 수집 시작 const startMonitoring = useCallback(() => { if (intervalRef.current) return; intervalRef.current = setInterval(async () => { const memoryUsage = measureMemoryUsage(); const networkLatency = await measureNetworkLatency(); setMetrics(prev => ({ ...prev, memoryUsage, networkLatency: Math.round(networkLatency * 100) / 100 })); updatePerformanceMetrics(); }, 5000); // 5초마다 수집 logger.info('System monitoring started'); }, [measureMemoryUsage, measureNetworkLatency, updatePerformanceMetrics]); // 메트릭 수집 중지 const stopMonitoring = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; logger.info('System monitoring stopped'); } }, []); // API 호출 시간 기록 const recordApiCallTime = useCallback((duration: number) => { apiCallTimes.current.push(duration); if (apiCallTimes.current.length > 10) { apiCallTimes.current = apiCallTimes.current.slice(-10); } }, []); // 컴포넌트 렌더링 시간 기록 const recordRenderTime = useCallback((duration: number) => { renderTimes.current.push(duration); if (renderTimes.current.length > 10) { renderTimes.current = renderTimes.current.slice(-10); } }, []); // 데이터 품질 업데이트 const updateDataQuality = useCallback((data: any[]) => { const quality = evaluateDataQuality(data); setMetrics(prev => ({ ...prev, dataQuality: quality })); if (quality.qualityScore < 80) { logger.warn('Data quality below threshold', { quality }); } }, [evaluateDataQuality]); // 센서 상태 업데이트 const updateSensorStatusData = useCallback((devices: any[]) => { const status = updateSensorStatus(devices); setMetrics(prev => ({ ...prev, sensorStatus: status })); }, [updateSensorStatus]); // WebSocket 상태 업데이트 const updateWebSocketStatus = useCallback((status: 'connected' | 'disconnected' | 'connecting') => { setMetrics(prev => ({ ...prev, websocketStatus: status })); }, []); useEffect(() => { startMonitoring(); return () => stopMonitoring(); }, [startMonitoring, stopMonitoring]); return { metrics, performanceMetrics, recordApiCallTime, recordRenderTime, updateDataQuality, updateSensorStatus: updateSensorStatusData, updateWebSocketStatus, startMonitoring, stopMonitoring }; };