Add PromQL queries display in historical analysis
- Include PromQL queries in API response for workload metrics - Display queries in historical analysis modal with copy functionality - Add professional styling for query display sections - Enable users to copy and validate queries in OpenShift Console - Organize queries by category: cluster totals, usage, requests, limits - Add copy-to-clipboard functionality with visual feedback
This commit is contained in:
@@ -744,6 +744,16 @@ async def get_workload_historical_metrics(
|
|||||||
"limits_percent": round(memory_limits_percent, 2),
|
"limits_percent": round(memory_limits_percent, 2),
|
||||||
"efficiency_percent": round(memory_efficiency, 1)
|
"efficiency_percent": round(memory_efficiency, 1)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"promql_queries": {
|
||||||
|
"cluster_cpu_total": cluster_cpu_query,
|
||||||
|
"cluster_memory_total": cluster_memory_query,
|
||||||
|
"cpu_usage": cpu_usage_query,
|
||||||
|
"memory_usage": memory_usage_query,
|
||||||
|
"cpu_requests": cpu_requests_query,
|
||||||
|
"memory_requests": memory_requests_query,
|
||||||
|
"cpu_limits": cpu_limits_query,
|
||||||
|
"memory_limits": memory_limits_query
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -781,6 +781,86 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PromQL Queries Styles */
|
||||||
|
.promql-queries {
|
||||||
|
margin-top: 30px;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.promql-queries h4 {
|
||||||
|
color: #495057;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.promql-queries h5 {
|
||||||
|
color: #6c757d;
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-section {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-item {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-item label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #495057;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.query-box code {
|
||||||
|
flex: 1;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #e83e8c;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn {
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn:hover {
|
||||||
|
background: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn:active {
|
||||||
|
background: #004085;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -1614,6 +1694,85 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
${data.promql_queries ? `
|
||||||
|
<div class="promql-queries" style="margin-top: 30px; padding: 20px; background: #f8f9fa; border-radius: 8px; border: 1px solid #dee2e6;">
|
||||||
|
<h4>🔍 PromQL Queries Used</h4>
|
||||||
|
<p style="color: #6c757d; margin-bottom: 15px;">Copy these queries to validate in OpenShift Console → Monitoring → Metrics:</p>
|
||||||
|
|
||||||
|
<div class="query-section">
|
||||||
|
<h5>Cluster Total Resources:</h5>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>CPU Total:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.cluster_cpu_total}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.cluster_cpu_total}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>Memory Total:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.cluster_memory_total}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.cluster_memory_total}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="query-section">
|
||||||
|
<h5>Workload Resource Usage:</h5>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>CPU Usage:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.cpu_usage}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.cpu_usage}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>Memory Usage:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.memory_usage}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.memory_usage}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="query-section">
|
||||||
|
<h5>Workload Resource Requests:</h5>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>CPU Requests:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.cpu_requests}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.cpu_requests}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>Memory Requests:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.memory_requests}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.memory_requests}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="query-section">
|
||||||
|
<h5>Workload Resource Limits:</h5>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>CPU Limits:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.cpu_limits}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.cpu_limits}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="query-item">
|
||||||
|
<label>Memory Limits:</label>
|
||||||
|
<div class="query-box">
|
||||||
|
<code>${data.promql_queries.memory_limits}</code>
|
||||||
|
<button onclick="copyToClipboard('${data.promql_queries.memory_limits}')" class="copy-btn">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1644,6 +1803,40 @@
|
|||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy to clipboard function for PromQL queries
|
||||||
|
async function copyToClipboard(text) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
// Show a brief success message
|
||||||
|
const button = event.target;
|
||||||
|
const originalText = button.textContent;
|
||||||
|
button.textContent = '✅ Copied!';
|
||||||
|
button.style.background = '#28a745';
|
||||||
|
setTimeout(() => {
|
||||||
|
button.textContent = originalText;
|
||||||
|
button.style.background = '';
|
||||||
|
}, 2000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to copy text: ', err);
|
||||||
|
// Fallback for older browsers
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = text;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
|
||||||
|
const button = event.target;
|
||||||
|
const originalText = button.textContent;
|
||||||
|
button.textContent = '✅ Copied!';
|
||||||
|
button.style.background = '#28a745';
|
||||||
|
setTimeout(() => {
|
||||||
|
button.textContent = originalText;
|
||||||
|
button.style.background = '';
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
function showLoading() {
|
function showLoading() {
|
||||||
document.getElementById('problemTableBody').innerHTML =
|
document.getElementById('problemTableBody').innerHTML =
|
||||||
|
|||||||
Reference in New Issue
Block a user