| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>NetDiag: Host & Connection Monitor</title> |
| |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| |
| <style> |
| :root { |
| --bg-color: #0f172a; |
| --card-bg: rgba(30, 41, 59, 0.7); |
| --card-border: rgba(148, 163, 184, 0.1); |
| --text-primary: #f1f5f9; |
| --text-secondary: #94a3b8; |
| --accent-cyan: #06b6d4; |
| --accent-green: #10b981; |
| --accent-red: #ef4444; |
| --accent-orange: #f59e0b; |
| --glow: 0 0 15px rgba(6, 182, 212, 0.3); |
| --font-main: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; |
| } |
| |
| * { |
| box-sizing: border-box; |
| margin: 0; |
| padding: 0; |
| } |
| |
| body { |
| font-family: var(--font-main); |
| background-color: var(--bg-color); |
| background-image: |
| radial-gradient(at 0% 0%, rgba(6, 182, 212, 0.15) 0px, transparent 50%), |
| radial-gradient(at 100% 100%, rgba(16, 185, 129, 0.15) 0px, transparent 50%); |
| color: var(--text-primary); |
| min-height: 100vh; |
| display: flex; |
| flex-direction: column; |
| overflow-x: hidden; |
| } |
| |
| |
| header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 1.5rem 2rem; |
| border-bottom: 1px solid var(--card-border); |
| backdrop-filter: blur(10px); |
| position: sticky; |
| top: 0; |
| z-index: 100; |
| background: rgba(15, 23, 42, 0.8); |
| } |
| |
| .brand { |
| display: flex; |
| align-items: center; |
| gap: 0.75rem; |
| font-size: 1.5rem; |
| font-weight: 700; |
| color: var(--accent-cyan); |
| text-shadow: 0 0 10px rgba(6, 182, 212, 0.4); |
| } |
| |
| .brand i { |
| font-size: 1.8rem; |
| } |
| |
| .anycoder-link { |
| font-size: 0.9rem; |
| color: var(--text-secondary); |
| text-decoration: none; |
| padding: 0.5rem 1rem; |
| border: 1px solid var(--card-border); |
| border-radius: 20px; |
| transition: all 0.3s ease; |
| } |
| |
| .anycoder-link:hover { |
| color: var(--text-primary); |
| border-color: var(--accent-cyan); |
| box-shadow: var(--glow); |
| } |
| |
| |
| main { |
| flex: 1; |
| padding: 2rem; |
| max-width: 1400px; |
| margin: 0 auto; |
| width: 100%; |
| display: grid; |
| grid-template-columns: repeat(12, 1fr); |
| gap: 1.5rem; |
| } |
| |
| |
| .card { |
| background: var(--card-bg); |
| border: 1px solid var(--card-border); |
| border-radius: 16px; |
| padding: 1.5rem; |
| backdrop-filter: blur(12px); |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); |
| display: flex; |
| flex-direction: column; |
| transition: transform 0.2s ease, box-shadow 0.2s ease; |
| } |
| |
| .card:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2); |
| } |
| |
| .card-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 1rem; |
| } |
| |
| .card-title { |
| font-size: 1rem; |
| font-weight: 600; |
| color: var(--text-secondary); |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| } |
| |
| |
| .status-panel { |
| grid-column: span 12; |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
| gap: 1.5rem; |
| } |
| |
| .chart-panel { |
| grid-column: span 8; |
| min-height: 400px; |
| } |
| |
| .log-panel { |
| grid-column: span 4; |
| min-height: 400px; |
| overflow: hidden; |
| } |
| |
| .controls-panel { |
| grid-column: span 12; |
| display: flex; |
| justify-content: flex-end; |
| gap: 1rem; |
| align-items: center; |
| } |
| |
| |
| .metric-value { |
| font-size: 2.5rem; |
| font-weight: 700; |
| margin: 0.5rem 0; |
| } |
| |
| .metric-unit { |
| font-size: 1rem; |
| color: var(--text-secondary); |
| font-weight: 400; |
| } |
| |
| .status-indicator { |
| width: 12px; |
| height: 12px; |
| border-radius: 50%; |
| background-color: var(--text-secondary); |
| box-shadow: 0 0 10px currentColor; |
| transition: background-color 0.3s ease, box-shadow 0.3s ease; |
| } |
| |
| .status-indicator.active { background-color: var(--accent-green); color: var(--accent-green); } |
| .status-indicator.warning { background-color: var(--accent-orange); color: var(--accent-orange); } |
| .status-indicator.critical { background-color: var(--accent-red); color: var(--accent-red); } |
| |
| |
| .progress-container { |
| width: 100%; |
| height: 8px; |
| background: rgba(255, 255, 255, 0.1); |
| border-radius: 4px; |
| overflow: hidden; |
| margin-top: 0.5rem; |
| } |
| |
| .progress-bar { |
| height: 100%; |
| width: 0%; |
| background: var(--accent-cyan); |
| border-radius: 4px; |
| transition: width 0.5s ease, background-color 0.3s ease; |
| position: relative; |
| } |
| |
| .progress-bar::after { |
| content: ''; |
| position: absolute; |
| top: 0; left: 0; right: 0; bottom: 0; |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent); |
| transform: translateX(-100%); |
| animation: shimmer 2s infinite; |
| } |
| |
| @keyframes shimmer { |
| 100% { transform: translateX(100%); } |
| } |
| |
| |
| canvas { |
| width: 100%; |
| height: 100%; |
| display: block; |
| } |
| |
| |
| .log-container { |
| font-family: 'Courier New', monospace; |
| font-size: 0.85rem; |
| color: var(--text-secondary); |
| overflow-y: auto; |
| flex: 1; |
| padding-right: 0.5rem; |
| display: flex; |
| flex-direction: column; |
| gap: 0.25rem; |
| } |
| |
| .log-entry { |
| display: flex; |
| gap: 0.5rem; |
| } |
| |
| .log-time { color: var(--accent-cyan); } |
| .log-msg-info { color: var(--text-primary); } |
| .log-msg-warn { color: var(--accent-orange); } |
| .log-msg-err { color: var(--accent-red); } |
| |
| |
| .btn { |
| padding: 0.75rem 1.5rem; |
| border-radius: 8px; |
| border: none; |
| font-weight: 600; |
| cursor: pointer; |
| transition: all 0.2s ease; |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| font-size: 0.95rem; |
| } |
| |
| .btn-primary { |
| background: var(--accent-cyan); |
| color: #0f172a; |
| } |
| |
| .btn-primary:hover { |
| background: #22d3ee; |
| box-shadow: 0 0 15px rgba(6, 182, 212, 0.5); |
| } |
| |
| .btn-danger { |
| background: transparent; |
| border: 1px solid var(--accent-red); |
| color: var(--accent-red); |
| } |
| |
| .btn-danger:hover { |
| background: rgba(239, 68, 68, 0.1); |
| } |
| |
| |
| #toast-container { |
| position: fixed; |
| bottom: 2rem; |
| right: 2rem; |
| display: flex; |
| flex-direction: column; |
| gap: 1rem; |
| z-index: 1000; |
| } |
| |
| .toast { |
| background: rgba(15, 23, 42, 0.95); |
| border-left: 4px solid var(--accent-cyan); |
| padding: 1rem 1.5rem; |
| border-radius: 4px; |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5); |
| color: var(--text-primary); |
| transform: translateX(120%); |
| transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); |
| display: flex; |
| align-items: center; |
| gap: 0.75rem; |
| backdrop-filter: blur(5px); |
| } |
| |
| .toast.show { |
| transform: translateX(0); |
| } |
| |
| |
| @media (max-width: 1024px) { |
| .chart-panel { grid-column: span 12; } |
| .log-panel { grid-column: span 12; min-height: 250px; } |
| } |
| |
| @media (max-width: 600px) { |
| header { flex-direction: column; gap: 1rem; } |
| .metric-value { font-size: 2rem; } |
| .controls-panel { flex-direction: column; align-items: stretch; } |
| } |
| </style> |
| </head> |
| <body> |
|
|
| <header> |
| <div class="brand"> |
| <i class="fa-solid fa-network-wired"></i> |
| <span>NetDiag</span> |
| </div> |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link"> |
| Built with anycoder <i class="fa-solid fa-arrow-up-right-from-square" style="font-size: 0.7em; margin-left:4px;"></i> |
| </a> |
| </header> |
|
|
| <main> |
| |
| <section class="status-panel"> |
| |
| |
| <div class="card"> |
| <div class="card-header"> |
| <div class="card-title"> |
| <i class="fa-solid fa-server"></i> Host CPU Load |
| </div> |
| <div id="host-status-light" class="status-indicator active"></div> |
| </div> |
| <div class="metric-value" id="cpu-val">0%</div> |
| <div class="progress-container"> |
| <div id="cpu-bar" class="progress-bar"></div> |
| </div> |
| <div style="margin-top: 0.5rem; font-size: 0.8rem; color: var(--text-secondary);"> |
| Limit: 90% (Throttling Threshold) |
| </div> |
| </div> |
|
|
| <div class="card"> |
| <div class="card-header"> |
| <div class="card-title"> |
| <i class="fa-solid fa-memory"></i> Memory Usage |
| </div> |
| </div> |
| <div class="metric-value" id="ram-val">0<span class="metric-unit">GB</span></div> |
| <div class="progress-container"> |
| <div id="ram-bar" class="progress-bar" style="background-color: var(--accent-green);"></div> |
| </div> |
| <div style="margin-top: 0.5rem; font-size: 0.8rem; color: var(--text-secondary);"> |
| Total: 16 GB |
| </div> |
| </div> |
|
|
| |
| <div class="card"> |
| <div class="card-header"> |
| <div class="card-title"> |
| <i class="fa-solid fa-wifi"></i> Connection Latency |
| </div> |
| <div id="conn-status-light" class="status-indicator active"></div> |
| </div> |
| <div class="metric-value" id="ping-val">0<span class="metric-unit">ms</span></div> |
| <div class="progress-container"> |
| <div id="ping-bar" class="progress-bar" style="background-color: var(--accent-orange);"></div> |
| </div> |
| <div style="margin-top: 0.5rem; font-size: 0.8rem; color: var(--text-secondary);"> |
| Jitter: <span id="jitter-val">0</span>ms |
| </div> |
| </div> |
|
|
| </section> |
|
|
| |
| <section class="card chart-panel"> |
| <div class="card-header"> |
| <div class="card-title"> |
| <i class="fa-solid fa-chart-line"></i> Real-Time Traffic Analysis |
| </div> |
| <div style="font-size: 0.8rem; color: var(--text-secondary);"> |
| <span style="color: var(--accent-cyan)">●</span> Requests |
| <span style="color: var(--accent-red)">●</span> Errors |
| </div> |
| </div> |
| <div style="flex: 1; position: relative;"> |
| <canvas id="trafficChart"></canvas> |
| </div> |
| </section> |
|
|
| |
| <section class="card log-panel"> |
| <div class="card-header"> |
| <div class="card-title"> |
| <i class="fa-solid fa-terminal"></i> System Logs |
| </div> |
| <button onclick="clearLogs()" style="background:none; border:none; color:var(--text-secondary); cursor:pointer;"> |
| <i class="fa-solid fa-trash"></i> |
| </button> |
| </div> |
| <div class="log-container" id="log-container"> |
| |
| </div> |
| </section> |
|
|
| |
| <section class="controls-panel"> |
| <button class="btn btn-danger" id="stop-btn" onclick="toggleMonitoring(false)" disabled> |
| <i class="fa-solid fa-stop"></i> Stop Monitor |
| </button> |
| <button class="btn btn-primary" id="start-btn" onclick="toggleMonitoring(true)"> |
| <i class="fa-solid fa-play"></i> Start Diagnostics |
| </button> |
| <button class="btn btn-primary" style="background: var(--accent-orange);" onclick="simulateSpike()"> |
| <i class="fa-solid fa-bolt"></i> Test Host Limit |
| </button> |
| </section> |
|
|
| </main> |
|
|
| |
| <div id="toast-container"></div> |
|
|
| <script> |
| |
| let isRunning = false; |
| let intervalId = null; |
| let chartIntervalId = null; |
| |
| |
| const maxDataPoints = 60; |
| let trafficData = new Array(maxDataPoints).fill(0); |
| let errorData = new Array(maxDataPoints).fill(0); |
| |
| |
| const cpuVal = document.getElementById('cpu-val'); |
| const cpuBar = document.getElementById('cpu-bar'); |
| const ramVal = document.getElementById('ram-val'); |
| const ramBar = document.getElementById('ram-bar'); |
| const pingVal = document.getElementById('ping-val'); |
| const pingBar = document.getElementById('ping-bar'); |
| const jitterVal = document.getElementById('jitter-val'); |
| |
| const hostLight = document.getElementById('host-status-light'); |
| const connLight = document.getElementById('conn-status-light'); |
| |
| const logContainer = document.getElementById('log-container'); |
| const canvas = document.getElementById('trafficChart'); |
| const ctx = canvas.getContext('2d'); |
| |
| |
| resizeCanvas(); |
| window.addEventListener('resize', resizeCanvas); |
| addLog("System initialized. Ready to diagnose.", "info"); |
| |
| |
| |
| function toggleMonitoring(start) { |
| if (start) { |
| if (isRunning) return; |
| isRunning = true; |
| document.getElementById('start-btn').disabled = true; |
| document.getElementById('stop-btn').disabled = false; |
| addLog("Diagnostics started...", "info"); |
| showToast("Monitoring Active", "success"); |
| |
| |
| intervalId = setInterval(updateMetrics, 1000); |
| |
| |
| chartIntervalId = setInterval(updateChartData, 100); |
| } else { |
| isRunning = false; |
| document.getElementById('start-btn').disabled = false; |
| document.getElementById('stop-btn').disabled = true; |
| clearInterval(intervalId); |
| clearInterval(chartIntervalId); |
| addLog("Diagnostics paused by user.", "warn"); |
| showToast("Monitoring Paused", "default"); |
| |
| |
| hostLight.className = "status-indicator"; |
| connLight.className = "status-indicator"; |
| } |
| } |
| |
| function updateMetrics() { |
| |
| |
| let cpu = Math.floor(Math.random() * 30) + 20; |
| let ram = (Math.random() * 2 + 4).toFixed(1); |
| |
| |
| if (Math.random() > 0.8) cpu += 30; |
| |
| |
| cpuVal.innerText = cpu + "%"; |
| cpuBar.style.width = cpu + "%"; |
| |
| if (cpu > 90) { |
| cpuBar.style.backgroundColor = "var(--accent-red)"; |
| hostLight.className = "status-indicator critical"; |
| if(Math.random() > 0.7) addLog("Host CPU Limit Critical! Throttling detected.", "err"); |
| } else if (cpu > 70) { |
| cpuBar.style.backgroundColor = "var(--accent-orange)"; |
| hostLight.className = "status-indicator warning"; |
| } else { |
| cpuBar.style.backgroundColor = "var(--accent-cyan)"; |
| hostLight.className = "status-indicator active"; |
| } |
| |
| |
| ramVal.innerHTML = ram + '<span class="metric-unit">GB</span>'; |
| const ramPercent = (ram / 16) * 100; |
| ramBar.style.width = ramPercent + "%"; |
| if(ramPercent > 80) ramBar.style.backgroundColor = "var(--accent-red)"; |
| else ramBar.style.backgroundColor = "var(--accent-green)"; |
| |
| |
| let ping = Math.floor(Math.random() * 40) + 10; |
| let jitter = Math.floor(Math.random() * 10); |
| |
| |
| if (Math.random() > 0.85) ping += 150; |
| |
| |
| pingVal.innerHTML = ping + '<span class="metric-unit">ms</span>'; |
| jitterVal.innerText = jitter; |
| |
| |
| const pingPercent = Math.min((ping / 200) * 100, 100); |
| pingBar.style.width = pingPercent + "%"; |
| |
| if (ping > 150) { |
| pingBar.style.backgroundColor = "var(--accent-red)"; |
| connLight.className = "status-indicator critical"; |
| if(Math.random() > 0.7) addLog(`Connection timeout: ${ping}ms latency.`, "err"); |
| } else if (ping > 80) { |
| pingBar.style.backgroundColor = "var(--accent-orange)"; |
| connLight.className = "status-indicator warning"; |
| } else { |
| pingBar.style.backgroundColor = "var(--accent-green)"; |
| connLight.className = "status-indicator active"; |
| } |
| } |
| |
| function updateChartData() { |
| |
| trafficData.shift(); |
| errorData.shift(); |
| |
| |
| |
| let newTraffic = Math.floor(Math.random() * 50) + 20; |
| let newError = Math.random() > 0.95 ? Math.floor(Math.random() * 40) : 0; |
| |
| trafficData.push(newTraffic); |
| errorData.push(newError); |
| |
| drawChart(); |
| } |
| |
| |
| function drawChart() { |
| const w = canvas.width; |
| const h = canvas.height; |
| |
| |
| ctx.clearRect(0, 0, w, h); |
| |
| |
| ctx.strokeStyle = "rgba(148, 163, 184, 0.1)"; |
| ctx.lineWidth = 1; |
| ctx.beginPath(); |
| for(let i=0; i<h; i+=40) { |
| ctx.moveTo(0, i); |
| ctx.lineTo(w, i); |
| } |
| ctx.stroke(); |
| |
| |
| drawLine(trafficData, "#06b6d4", 2); |
| |
| |
| drawLine(errorData, "#ef4444", 2); |
| } |
| |
| function drawLine(data, color, width) { |
| const w = canvas.width; |
| const h = canvas.height; |
| const step = w / (maxDataPoints - 1); |
| |
| ctx.beginPath(); |
| ctx.strokeStyle = color; |
| ctx.lineWidth = width; |
| ctx.lineJoin = 'round'; |
| |
| for (let i = 0; i < data.length; i++) { |
| |
| |
| const y = h - ((data[i] / 100) * h); |
| const x = i * step; |
| |
| if (i === 0) ctx.moveTo(x, y); |
| else ctx.lineTo(x, y); |
| } |
| ctx.stroke(); |
| |
| |
| ctx.lineTo(w, h); |
| ctx.lineTo(0, h); |
| ctx.closePath(); |
| |
| const gradient = ctx.createLinearGradient(0, 0, 0, h); |
| gradient.addColorStop(0, color + "44"); |
| gradient.addColorStop(1, color + "00"); |
| ctx.fillStyle = gradient; |
| ctx.fill(); |
| } |
| |
| function resizeCanvas() { |
| |
| const container = canvas.parentElement; |
| canvas.width = container.clientWidth; |
| canvas.height = container.clientHeight; |
| drawChart(); |
| } |
| |
| |
| function simulateSpike() { |
| if(!isRunning) { |
| showToast("Start monitoring first!", "warn"); |
| return; |
| } |
| |
| |
| cpuVal.innerText = "98%"; |
| cpuBar.style.width = "98%"; |
| cpuBar.style.backgroundColor = "var(--accent-red)"; |
| hostLight.className = "status-indicator critical"; |
| |
| addLog("MANUAL TEST: Simulating Host Limit Breach...", "err"); |
| showToast("Host Limit Test Triggered", "error"); |
| |
| |
| for(let i=0; i<20; i++) { |
| trafficData.push(Math.random() * 20 + 80); |
| trafficData.shift(); |
| } |
| } |
| |
| |
| |
| function addLog(msg, type) { |
| const time = new Date().toLocaleTimeString('en-US', { hour12: false }); |
| const div = document.createElement('div'); |
| div.className = 'log-entry'; |
| |
| let colorClass = "log-msg-info"; |
| if (type === "warn") colorClass = "log-msg-warn"; |
| if (type === "err") colorClass = "log-msg-err"; |
| |
| div.innerHTML = `<span class="log-time">[${time}]</span> <span class="${colorClass}">${msg}</span>`; |
| |
| logContainer.appendChild(div); |
| logContainer.scrollTop = logContainer.scrollHeight; |
| } |
| |
| function clearLogs() { |
| logContainer.innerHTML = ''; |
| addLog("Logs cleared.", "info"); |
| } |
| |
| function showToast(message, type = "default") { |
| const container = document.getElementById('toast-container'); |
| const toast = document.createElement('div'); |
| toast.className = 'toast'; |
| |
| let icon = '<i class="fa-solid fa-info-circle"></i>'; |
| let color = 'var(--accent-cyan)'; |
| |
| if (type === 'success') { |
| icon = '<i class="fa-solid fa-check-circle"></i>'; |
| color = 'var(--accent-green)'; |
| } else if (type === 'error') { |
| icon = '<i class="fa-solid fa-triangle-exclamation"></i>'; |
| color = 'var(--accent-red)'; |
| } else if (type === 'warn') { |
| icon = '<i class="fa-solid fa-exclamation-circle"></i>'; |
| color = 'var(--accent-orange)'; |
| } |
| |
| toast.style.borderLeftColor = color; |
| toast.innerHTML = `<span style="color:${color}; font-size: 1.2rem;">${icon}</span> ${message}`; |
| |
| container.appendChild(toast); |
| |
| |
| requestAnimationFrame(() => { |
| toast.classList.add('show'); |
| }); |
| |
| |
| setTimeout(() => { |
| toast.classList.remove('show'); |
| setTimeout(() => { |
| toast.remove(); |
| }, 300); |
| }, 3000); |
| } |
| |
| </script> |
| </body> |
| </html> |