import React, { useState, useEffect } from 'react'; import api from '../api'; import { reportError, logUserActionError } from '../utils/errorLogger'; const LogMonitoringPage = ({ onNavigate, user }) => { const [activeTab, setActiveTab] = useState('login-logs'); // 'login-logs', 'activity-logs', 'system-logs' const [stats, setStats] = useState({ totalUsers: 0, activeUsers: 0, todayLogins: 0, failedLogins: 0, recentErrors: 0 }); const [recentActivity, setRecentActivity] = useState([]); const [activityLogs, setActivityLogs] = useState([]); const [frontendErrors, setFrontendErrors] = useState([]); const [isLoading, setIsLoading] = useState(true); const [message, setMessage] = useState({ type: '', text: '' }); useEffect(() => { loadDashboardData(); // 30초마다 자동 새로고침 const interval = setInterval(loadDashboardData, 30000); return () => clearInterval(interval); }, []); const loadActivityLogs = async () => { try { const response = await api.get('/auth/logs/system?limit=50'); if (response.data.success) { setActivityLogs(response.data.logs); } } catch (error) { console.error('활동 로그 로딩 실패:', error); } }; const loadDashboardData = async () => { try { setIsLoading(true); // 활동 로그도 함께 로드 if (activeTab === 'activity-logs') { await loadActivityLogs(); } // 병렬로 데이터 로드 const [usersResponse, loginLogsResponse] = await Promise.all([ api.get('/auth/users'), api.get('/auth/logs/login', { params: { limit: 20 } }) ]); // 사용자 통계 if (usersResponse.data.success) { const users = usersResponse.data.users; setStats(prev => ({ ...prev, totalUsers: users.length, activeUsers: users.filter(u => u.is_active).length })); } // 로그인 로그 통계 if (loginLogsResponse.data.success) { const logs = loginLogsResponse.data.logs; const today = new Date().toDateString(); const todayLogins = logs.filter(log => new Date(log.login_time).toDateString() === today && log.login_status === 'success' ).length; const failedLogins = logs.filter(log => new Date(log.login_time).toDateString() === today && log.login_status === 'failed' ).length; setStats(prev => ({ ...prev, todayLogins, failedLogins })); setRecentActivity(logs.slice(0, 10)); } // 프론트엔드 오류 로그 (로컬 스토리지에서) const localErrors = JSON.parse(localStorage.getItem('frontend_errors') || '[]'); const recentErrors = localErrors.filter(error => { const errorDate = new Date(error.timestamp); const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000); return errorDate > oneDayAgo; }); setFrontendErrors(recentErrors.slice(0, 10)); setStats(prev => ({ ...prev, recentErrors: recentErrors.length })); } catch (err) { console.error('Load dashboard data error:', err); setMessage({ type: 'error', text: '대시보드 데이터 로드 중 오류가 발생했습니다' }); logUserActionError('load_dashboard_data', err, { userId: user?.user_id }); } finally { setIsLoading(false); } }; const clearFrontendErrors = () => { localStorage.removeItem('frontend_errors'); setFrontendErrors([]); setStats(prev => ({ ...prev, recentErrors: 0 })); setMessage({ type: 'success', text: '프론트엔드 오류 로그가 삭제되었습니다' }); }; const formatDateTime = (dateString) => { try { return new Date(dateString).toLocaleString('ko-KR', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); } catch { return dateString; } }; const getActivityIcon = (status) => { return status === 'success' ? '✅' : '❌'; }; const getErrorTypeIcon = (type) => { const icons = { 'javascript_error': '❌', 'api_error': '🌐', 'user_action_error': '👤', 'promise_rejection': '⚠️', 'react_error_boundary': '⚛️' }; return icons[type] || '❓'; }; return (
{/* 헤더 */}

📈 로그 모니터링

{/* 탭 네비게이션 */}
{frontendErrors.length > 0 && ( )}
{/* 메시지 표시 */} {message.text && (
{message.text}
)} {/* 통계 카드 */}
👥

전체 사용자

{stats.totalUsers}
활성: {stats.activeUsers}명

오늘 로그인

{stats.todayLogins}
성공한 로그인

로그인 실패

{stats.failedLogins}
오늘 실패 횟수

최근 오류

{stats.recentErrors}
24시간 내
{/* 콘텐츠 그리드 */}
{/* 최근 활동 */}

🔐 최근 로그인 활동

{isLoading ? (
로딩 중...
) : recentActivity.length === 0 ? (
최근 활동이 없습니다
) : ( recentActivity.map((activity, index) => (
{getActivityIcon(activity.login_status)}
{activity.name}
@{activity.username} • {activity.ip_address}
{activity.failure_reason && (
{activity.failure_reason}
)}
{formatDateTime(activity.login_time)}
)) )}
{/* 프론트엔드 오류 */}

❌ 프론트엔드 오류

{frontendErrors.length === 0 ? (
최근 오류가 없습니다
) : ( frontendErrors.map((error, index) => (
{getErrorTypeIcon(error.type)}
{error.type?.replace('_', ' ').toUpperCase() || 'ERROR'}
{error.message?.substring(0, 100)} {error.message?.length > 100 && '...'}
{error.url && ( {new URL(error.url).pathname} • )} {formatDateTime(error.timestamp)}
)) )}
{/* 자동 새로고침 안내 */}

📊 이 페이지는 30초마다 자동으로 새로고침됩니다

); }; export default LogMonitoringPage;