// 全局变量 let currentSection = 'dashboard'; let refreshInterval = null; let charts = {}; // API基础URL const API_BASE = '/monitor'; // 初始化 document.addEventListener('DOMContentLoaded', function() { initializeDashboard(); startAutoRefresh(); }); // 初始化仪表盘 function initializeDashboard() { showSection('dashboard'); loadDashboardData(); } // 显示指定区域 function showSection(section) { // 隐藏所有区域 document.querySelectorAll('.section').forEach(el => { el.classList.add('hidden'); }); // 显示指定区域 document.getElementById(section + '-section').classList.remove('hidden'); // 更新侧边栏状态 document.querySelectorAll('.sidebar-item').forEach(el => { el.classList.remove('active'); }); event.currentTarget.classList.add('active'); // 更新标题 const titles = { 'dashboard': '仪表盘', 'health': '健康检查', 'metrics': '性能指标', 'errors': '错误追踪', 'logs': '日志分析', 'alerts': '告警管理', 'settings': '系统设置' }; document.getElementById('section-title').textContent = titles[section]; currentSection = section; // 加载对应数据 loadSectionData(section); } // 加载区域数据 function loadSectionData(section) { switch(section) { case 'dashboard': loadDashboardData(); break; case 'health': loadHealthData(); break; case 'metrics': loadMetricsData(); break; case 'errors': loadErrorsData(); break; case 'logs': // 日志数据需要用户主动搜索 break; case 'alerts': loadAlertsData(); break; case 'settings': loadSettingsData(); break; } } // 加载仪表盘数据 async function loadDashboardData() { try { // 加载健康状态 const healthResponse = await fetch(`${API_BASE}/health`); const health = await healthResponse.json(); updateDashboardHealth(health.data); // 加载指标数据 const metricsResponse = await fetch(`${API_BASE}/metrics`); const metrics = await metricsResponse.json(); updateDashboardMetrics(metrics.data); // 加载告警数据 const alertsResponse = await fetch(`${API_BASE}/alerts/active`); const alerts = await alertsResponse.json(); updateDashboardAlerts(alerts.data); // 加载图表数据 loadDashboardCharts(); // 更新时间 updateLastUpdateTime(); } catch (error) { console.error('加载仪表盘数据失败:', error); showError('加载仪表盘数据失败'); } } // 更新仪表盘健康状态 function updateDashboardHealth(health) { const statusEl = document.getElementById('system-status'); const statusClass = health.status === 'healthy' ? 'status-healthy' : health.status === 'warning' ? 'status-warning' : 'status-critical'; statusEl.textContent = health.status === 'healthy' ? '健康' : health.status === 'warning' ? '警告' : '严重'; statusEl.className = `text-2xl font-bold ${statusClass}`; } // 更新仪表盘指标 function updateDashboardMetrics(metrics) { if (metrics.system) { const memoryUsage = metrics.system.memory_usage; const memoryLimit = metrics.system.memory_limit; const memoryPercent = memoryLimit > 0 ? (memoryUsage / memoryLimit * 100).toFixed(1) : 0; document.getElementById('memory-usage').textContent = memoryPercent + '%'; } // 计算平均响应时间 if (metrics.histograms && metrics.histograms.http_request_duration) { const avgTime = metrics.histograms.http_request_duration.mean || 0; document.getElementById('response-time').textContent = avgTime.toFixed(2) + 'ms'; } } // 更新仪表盘告警 function updateDashboardAlerts(alerts) { document.getElementById('active-alerts').textContent = alerts.length; const recentAlertsEl = document.getElementById('recent-alerts'); if (alerts.length === 0) { recentAlertsEl.innerHTML = '

暂无告警

'; } else { recentAlertsEl.innerHTML = alerts.slice(0, 5).map(alert => `

${alert.type}

${alert.message}

${formatTime(alert.timestamp)}

`).join(''); } } // 加载仪表盘图表 async function loadDashboardCharts() { try { // 加载请求数据 const statsResponse = await fetch(`${API_BASE}/stats`); const stats = await statsResponse.json(); // 请求趋势图 if (charts.requests) { charts.requests.destroy(); } const requestsChart = { series: [{ name: '请求数', data: generateTimeSeriesData() }], chart: { type: 'area', height: 300, toolbar: { show: false } }, dataLabels: { enabled: false }, stroke: { curve: 'smooth', width: 2 }, fill: { type: 'gradient', gradient: { shadeIntensity: 1, opacityFrom: 0.7, opacityTo: 0.3 } }, xaxis: { categories: generateTimeLabels() }, yaxis: { title: { text: '请求数' } }, colors: ['#3b82f6'] }; charts.requests = new ApexCharts(document.getElementById('requests-chart'), requestsChart); charts.requests.render(); // 错误分布图 if (charts.errors) { charts.errors.destroy(); } const errorsData = stats.data?.system?.error_count || 0; const errorsChart = { series: [errorsData, Math.max(0, 100 - errorsData)], chart: { type: 'donut', height: 300 }, labels: ['错误', '正常'], colors: ['#ef4444', '#10b981'], legend: { position: 'bottom' }, dataLabels: { enabled: true } }; charts.errors = new ApexCharts(document.getElementById('errors-chart'), errorsChart); charts.errors.render(); } catch (error) { console.error('加载图表失败:', error); } } // 加载健康检查数据 async function loadHealthData() { try { const response = await fetch(`${API_BASE}/health`); const result = await response.json(); const healthChecksEl = document.getElementById('health-checks'); const checks = result.data.checks; healthChecksEl.innerHTML = Object.entries(checks).map(([name, check]) => `

${getComponentName(name)}

${check.message || '运行正常'}

${check.status === 'healthy' ? '健康' : check.status === 'warning' ? '警告' : '严重'}

${check.duration ? check.duration.toFixed(3) + 's' : ''}

`).join(''); } catch (error) { console.error('加载健康检查数据失败:', error); showError('加载健康检查数据失败'); } } // 加载指标数据 async function loadMetricsData() { try { const response = await fetch(`${API_BASE}/metrics`); const result = await response.json(); const metrics = result.data; // 系统指标 const systemMetricsEl = document.getElementById('system-metrics'); if (metrics.system) { systemMetricsEl.innerHTML = `
内存使用 ${formatBytes(metrics.system.memory_usage)} / ${formatBytes(metrics.system.memory_limit)}
CPU使用率 ${(metrics.system.cpu_usage * 100).toFixed(1)}%
运行时间 ${formatUptime(metrics.system.uptime)}
负载均衡 ${metrics.system.load_avg ? metrics.system.load_avg[0].toFixed(2) : 'N/A'}
`; } // 应用指标 const appMetricsEl = document.getElementById('application-metrics'); const totalRequests = Object.values(metrics.counters || {}).reduce((sum, count) => sum + count, 0); const totalErrors = Object.values(metrics.counters || {}).filter(key => key.includes('error')).reduce((sum, count) => sum + count, 0); appMetricsEl.innerHTML = `
总请求数 ${totalRequests}
总错误数 ${totalErrors}
成功率 ${totalRequests > 0 ? ((totalRequests - totalErrors) / totalRequests * 100).toFixed(1) : 100}%
活跃连接 ${metrics.gauges?.requests_in_progress || 0}
`; } catch (error) { console.error('加载指标数据失败:', error); showError('加载指标数据失败'); } } // 加载错误数据 async function loadErrorsData() { try { const filter = document.getElementById('error-filter').value; const response = await fetch(`${API_BASE}/errors${filter ? '?severity=' + filter : ''}`); const result = await response.json(); const errorsListEl = document.getElementById('errors-list'); if (result.data.length === 0) { errorsListEl.innerHTML = '

暂无错误记录

'; } else { errorsListEl.innerHTML = result.data.map(error => `
${error.severity.toUpperCase()} ${error.type}

${error.message}

文件: ${error.file || 'N/A'}:${error.line || 'N/A'}

时间: ${formatTime(error.timestamp)}

Trace ID: ${error.trace_id || 'N/A'}

`).join(''); } } catch (error) { console.error('加载错误数据失败:', error); showError('加载错误数据失败'); } } // 搜索日志 async function searchLogs() { const level = document.getElementById('log-level').value; const search = document.getElementById('log-search').value; const params = new URLSearchParams(); if (level) params.append('level', level); if (search) params.append('message', search); params.append('limit', '50'); try { const response = await fetch(`${API_BASE}/logs/search?${params}`); const result = await response.json(); const logsContainerEl = document.getElementById('logs-container'); if (result.data.logs.length === 0) { logsContainerEl.innerHTML = '

未找到匹配的日志

'; } else { logsContainerEl.innerHTML = result.data.logs.map(log => `
${log.level} ${log.datetime}
${log.trace_id || ''}

${log.message}

`).join(''); } } catch (error) { console.error('搜索日志失败:', error); showError('搜索日志失败'); } } // 加载告警数据 async function loadAlertsData() { try { const status = document.getElementById('alert-status').value; const response = await fetch(`${API_BASE}/alerts${status ? '?status=' + status : ''}`); const result = await response.json(); const alertsListEl = document.getElementById('alerts-list'); if (result.data.length === 0) { alertsListEl.innerHTML = '

暂无告警

'; } else { alertsListEl.innerHTML = result.data.map(alert => `
${alert.type} ${alert.status === 'active' ? '活跃' : alert.status === 'acknowledged' ? '已确认' : '已解决'}

${alert.message}

时间: ${formatTime(alert.timestamp)}

${alert.status === 'active' ? ` ` : ''}
`).join(''); } } catch (error) { console.error('加载告警数据失败:', error); showError('加载告警数据失败'); } } // 加载设置数据 async function loadSettingsData() { try { // 这里可以加载实际的配置数据 // 暂时使用默认值 document.getElementById('sample-rate').value = '1.0'; document.getElementById('retention').value = '3600'; document.getElementById('error-threshold').value = '0.05'; document.getElementById('memory-threshold').value = '0.8'; } catch (error) { console.error('加载设置数据失败:', error); showError('加载设置数据失败'); } } // 确认告警 async function acknowledgeAlert(alertId) { try { const response = await fetch(`${API_BASE}/alerts/${alertId}/acknowledge`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ acknowledged_by: 'admin' }) }); if (response.ok) { showSuccess('告警已确认'); if (currentSection === 'dashboard') { loadDashboardData(); } else if (currentSection === 'alerts') { loadAlertsData(); } } else { showError('确认告警失败'); } } catch (error) { console.error('确认告警失败:', error); showError('确认告警失败'); } } // 解决告警 async function resolveAlert(alertId) { try { const response = await fetch(`${API_BASE}/alerts/${alertId}/resolve`, { method: 'POST' }); if (response.ok) { showSuccess('告警已解决'); if (currentSection === 'dashboard') { loadDashboardData(); } else if (currentSection === 'alerts') { loadAlertsData(); } } else { showError('解决告警失败'); } } catch (error) { console.error('解决告警失败:', error); showError('解决告警失败'); } } // 保存设置 async function saveSettings() { try { const settings = { sample_rate: parseFloat(document.getElementById('sample-rate').value), retention: parseInt(document.getElementById('retention').value), error_threshold: parseFloat(document.getElementById('error-threshold').value), memory_threshold: parseFloat(document.getElementById('memory-threshold').value) }; // 这里应该发送到后端保存 console.log('保存设置:', settings); showSuccess('设置已保存'); } catch (error) { console.error('保存设置失败:', error); showError('保存设置失败'); } } // 刷新数据 function refreshData() { loadSectionData(currentSection); } // 刷新错误数据 function refreshErrors() { loadErrorsData(); } // 刷新告警数据 function refreshAlerts() { loadAlertsData(); } // 开始自动刷新 function startAutoRefresh() { refreshInterval = setInterval(() => { if (currentSection !== 'settings') { loadSectionData(currentSection); } }, 30000); // 30秒刷新一次 } // 停止自动刷新 function stopAutoRefresh() { if (refreshInterval) { clearInterval(refreshInterval); refreshInterval = null; } } // 更新最后更新时间 function updateLastUpdateTime() { document.getElementById('last-update').textContent = '最后更新: ' + new Date().toLocaleTimeString(); } // 工具函数 function formatTime(timestamp) { return new Date(timestamp * 1000).toLocaleString(); } function formatBytes(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } function formatUptime(seconds) { const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) { return `${days}天 ${hours}小时`; } else if (hours > 0) { return `${hours}小时 ${minutes}分钟`; } else { return `${minutes}分钟`; } } function getComponentName(name) { const names = { 'database': '数据库', 'cache': '缓存', 'filesystem': '文件系统', 'memory': '内存', 'disk': '磁盘', 'external_services': '外部服务' }; return names[name] || name; } function getLogLevelColor(level) { const colors = { 'DEBUG': 'gray', 'INFO': 'blue', 'WARNING': 'yellow', 'ERROR': 'red', 'CRITICAL': 'red' }; return colors[level] || 'gray'; } function generateTimeSeriesData() { // 生成模拟数据 return Array.from({length: 24}, () => Math.floor(Math.random() * 100) + 50); } function generateTimeLabels() { const labels = []; const now = new Date(); for (let i = 23; i >= 0; i--) { const time = new Date(now.getTime() - i * 60 * 60 * 1000); labels.push(time.getHours() + ':00'); } return labels; } function showSuccess(message) { // 显示成功消息 console.log('Success:', message); } function showError(message) { // 显示错误消息 console.error('Error:', message); } // 页面卸载时清理 window.addEventListener('beforeunload', stopAutoRefresh);