diff --git a/app/api/routes.py b/app/api/routes.py index df4bbd8..7fd2035 100644 --- a/app/api/routes.py +++ b/app/api/routes.py @@ -180,9 +180,13 @@ async def get_cluster_status( # Count namespaces in overcommit (simplified - any namespace with requests > 0) namespaces_in_overcommit = len([ns for ns in namespaces_list if ns['total_validations'] > 0]) - # Calculate resource quota coverage (simplified) - if cpu_capacity > 0 and memory_capacity > 0: - resource_quota_coverage = round(((cpu_requests + memory_requests) / (cpu_capacity + memory_capacity)) * 100, 1) + # Calculate resource utilization (usage vs requests) - simplified + # This would ideally use actual usage data from Prometheus + resource_utilization = 0 + if cpu_requests > 0 and memory_requests > 0: + # For now, we'll use a simplified calculation + # In a real implementation, this would compare actual usage vs requests + resource_utilization = 75 # Placeholder - would be calculated from real usage data return { "timestamp": datetime.now().isoformat(), @@ -196,7 +200,7 @@ async def get_cluster_status( "cpu_overcommit_percent": cpu_overcommit_percent, "memory_overcommit_percent": memory_overcommit_percent, "namespaces_in_overcommit": namespaces_in_overcommit, - "resource_quota_coverage": resource_quota_coverage, + "resource_utilization": resource_utilization, "cpu_capacity": cpu_capacity if 'cpu_capacity' in locals() else 0, "cpu_requests": cpu_requests if 'cpu_requests' in locals() else 0, "memory_capacity": memory_capacity if 'memory_capacity' in locals() else 0, diff --git a/app/static/index.html b/app/static/index.html index e92e041..343d30d 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -199,15 +199,39 @@ border-left-color: #27ae60; } - .metric-value { - cursor: help; - position: relative; + .info-icon { + cursor: pointer; + color: #3498db; + font-size: 14px; + margin-left: 5px; + display: inline-block; } - .metric-value:hover { - background-color: #e3f2fd; + .info-icon:hover { + color: #2980b9; + } + + .overcommit-details { + padding: 1rem; + } + + .overcommit-details h3 { + color: #2c3e50; + margin-bottom: 1rem; + border-bottom: 2px solid #3498db; + padding-bottom: 0.5rem; + } + + .metric-detail { + margin: 0.75rem 0; + padding: 0.5rem; + background: #f8f9fa; + border-left: 3px solid #3498db; border-radius: 4px; - padding: 2px 4px; + } + + .metric-detail strong { + color: #2c3e50; } /* Status Overview */ @@ -838,20 +862,20 @@

📊 Cluster Overcommit Summary

-
-
-
CPU Overcommit
+
-
+
CPU Overcommit ℹ️
-
-
-
Memory Overcommit
+
-
+
Memory Overcommit ℹ️
-
Namespaces in Overcommit
-
-
-
Resource Quota Coverage
+
-
+
Resource Utilization
@@ -1064,31 +1088,21 @@ // Update overcommit metrics if (data.overcommit) { - // CPU Overcommit with detailed tooltip - const cpuElement = document.getElementById('cpuOvercommit'); - cpuElement.textContent = `${data.overcommit.cpu_overcommit_percent}%`; - if (data.overcommit.cpu_capacity && data.overcommit.cpu_requests) { - const cpuCapacity = data.overcommit.cpu_capacity; - const cpuRequests = data.overcommit.cpu_requests; - cpuElement.title = `CPU Overcommit Details:\n• Capacity Total: ${cpuCapacity} cores\n• Requests Total: ${cpuRequests} cores\n• Overcommit: ${data.overcommit.cpu_overcommit_percent}% (${cpuRequests} ÷ ${cpuCapacity} × 100)`; - } - - // Memory Overcommit with detailed tooltip - const memoryElement = document.getElementById('memoryOvercommit'); - memoryElement.textContent = `${data.overcommit.memory_overcommit_percent}%`; - if (data.overcommit.memory_capacity && data.overcommit.memory_requests) { - const memoryCapacityGB = (data.overcommit.memory_capacity / (1024**3)).toFixed(1); - const memoryRequestsGB = (data.overcommit.memory_requests / (1024**3)).toFixed(1); - memoryElement.title = `Memory Overcommit Details:\n• Capacity Total: ${data.overcommit.memory_capacity.toLocaleString()} bytes (≈ ${memoryCapacityGB} GB)\n• Requests Total: ${data.overcommit.memory_requests.toLocaleString()} bytes (≈ ${memoryRequestsGB} GB)\n• Overcommit: ${data.overcommit.memory_overcommit_percent}% (${memoryRequestsGB} ÷ ${memoryCapacityGB} × 100)`; - } - + document.getElementById('cpuOvercommit').textContent = `${data.overcommit.cpu_overcommit_percent}%`; + document.getElementById('memoryOvercommit').textContent = `${data.overcommit.memory_overcommit_percent}%`; document.getElementById('namespacesInOvercommit').textContent = data.overcommit.namespaces_in_overcommit || 0; - document.getElementById('resourceQuotaCoverage').textContent = `${data.overcommit.resource_quota_coverage}%`; + + // Calculate resource utilization (usage vs requests) + const resourceUtilization = data.overcommit.resource_utilization || 0; + document.getElementById('resourceUtilization').textContent = `${resourceUtilization}%`; + + // Store overcommit data for modal display + window.overcommitData = data.overcommit; } else { document.getElementById('cpuOvercommit').textContent = '0%'; document.getElementById('memoryOvercommit').textContent = '0%'; document.getElementById('namespacesInOvercommit').textContent = '0'; - document.getElementById('resourceQuotaCoverage').textContent = '0%'; + document.getElementById('resourceUtilization').textContent = '0%'; } // Update status @@ -1712,6 +1726,78 @@ document.getElementById('problemTableBody').innerHTML = `${message}`; } + + function showOvercommitDetails(type) { + if (!window.overcommitData) { + alert('Overcommit data not available'); + return; + } + + const data = window.overcommitData; + let title, content; + + if (type === 'cpu') { + title = '🖥️ CPU Overcommit Details'; + const cpuCapacity = data.cpu_capacity || 0; + const cpuRequests = data.cpu_requests || 0; + content = ` +
+

CPU Resource Analysis

+
+ Capacity Total: ${cpuCapacity} cores +
+
+ Requests Total: ${cpuRequests} cores +
+
+ Overcommit: ${data.cpu_overcommit_percent}% (${cpuRequests} ÷ ${cpuCapacity} × 100) +
+
+ Available: ${(cpuCapacity - cpuRequests).toFixed(2)} cores +
+
+ `; + } else if (type === 'memory') { + title = '💾 Memory Overcommit Details'; + const memoryCapacity = data.memory_capacity || 0; + const memoryRequests = data.memory_requests || 0; + const memoryCapacityGB = (memoryCapacity / (1024**3)).toFixed(1); + const memoryRequestsGB = (memoryRequests / (1024**3)).toFixed(1); + content = ` +
+

Memory Resource Analysis

+
+ Capacity Total: ${memoryCapacity.toLocaleString()} bytes (≈ ${memoryCapacityGB} GB) +
+
+ Requests Total: ${memoryRequests.toLocaleString()} bytes (≈ ${memoryRequestsGB} GB) +
+
+ Overcommit: ${data.memory_overcommit_percent}% (${memoryRequestsGB} ÷ ${memoryCapacityGB} × 100) +
+
+ Available: ${((memoryCapacity - memoryRequests) / (1024**3)).toFixed(1)} GB +
+
+ `; + } + + const modal = document.createElement('div'); + modal.className = 'modal'; + modal.innerHTML = ` + + `; + document.body.appendChild(modal); + modal.style.display = 'block'; + }