docs: update CLI command syntax across workflow documentation
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Waiting to run
CLI Tests / test-cli (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Documentation Validation / validate-docs (push) Has been cancelled
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Waiting to run
CLI Tests / test-cli (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Documentation Validation / validate-docs (push) Has been cancelled
- Updated marketplace commands: `marketplace --action` → `market` subcommands - Updated wallet commands: direct flags → `wallet` subcommands - Updated AI commands: `ai-submit`, `ai-status` → `ai submit`, `ai status` - Updated blockchain commands: `chain` → `blockchain info` - Standardized command structure across all workflow files - Affected files: MULTI_NODE_MASTER_INDEX.md, TEST_MASTER_INDEX.md, multi-node-blockchain-marketplace
This commit is contained in:
312
website/dashboards/metrics.html
Normal file
312
website/dashboards/metrics.html
Normal file
@@ -0,0 +1,312 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AITBC Metrics Dashboard</title>
|
||||
<link rel="stylesheet" href="/assets/css/site-header.css">
|
||||
<link rel="stylesheet" href="/assets/css/dashboards.css">
|
||||
<link rel="preload" href="/assets/css/font-awesome.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
||||
</head>
|
||||
<body>
|
||||
<div data-global-header></div>
|
||||
|
||||
<main>
|
||||
<div class="container">
|
||||
<!-- Header -->
|
||||
<div class="dashboard-header">
|
||||
<h1><i class="fas fa-chart-line"></i> System Metrics Dashboard</h1>
|
||||
<p>Real-time monitoring of AITBC system performance and health</p>
|
||||
<div class="last-updated">
|
||||
<span>Last Updated: <span id="last-updated">Loading...</span></span>
|
||||
<button onclick="refreshMetrics()" class="btn btn-primary">
|
||||
<i class="fas fa-sync-alt"></i> Refresh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metrics Grid -->
|
||||
<div class="metrics-grid">
|
||||
<!-- API Metrics -->
|
||||
<div class="metric-card">
|
||||
<div class="metric-header">
|
||||
<h3><i class="fas fa-server"></i> API Metrics</h3>
|
||||
</div>
|
||||
<div class="metric-body">
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Total Requests</span>
|
||||
<span class="metric-value" id="api-requests">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Errors</span>
|
||||
<span class="metric-value error" id="api-errors">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Error Rate</span>
|
||||
<span class="metric-value" id="error-rate">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Avg Response Time</span>
|
||||
<span class="metric-value" id="avg-response-time">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Database Metrics -->
|
||||
<div class="metric-card">
|
||||
<div class="metric-header">
|
||||
<h3><i class="fas fa-database"></i> Database Metrics</h3>
|
||||
</div>
|
||||
<div class="metric-body">
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Queries</span>
|
||||
<span class="metric-value" id="db-queries">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Errors</span>
|
||||
<span class="metric-value error" id="db-errors">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Active Connections</span>
|
||||
<span class="metric-value" id="active-connections">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Cache Metrics -->
|
||||
<div class="metric-card">
|
||||
<div class="metric-header">
|
||||
<h3><i class="fas fa-memory"></i> Cache Metrics</h3>
|
||||
</div>
|
||||
<div class="metric-body">
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Cache Hits</span>
|
||||
<span class="metric-value success" id="cache-hits">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Cache Misses</span>
|
||||
<span class="metric-value warning" id="cache-misses">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Hit Rate</span>
|
||||
<span class="metric-value" id="cache-hit-rate">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Metrics -->
|
||||
<div class="metric-card">
|
||||
<div class="metric-header">
|
||||
<h3><i class="fas fa-microchip"></i> System Metrics</h3>
|
||||
</div>
|
||||
<div class="metric-body">
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Memory Usage</span>
|
||||
<span class="metric-value" id="memory-usage">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">CPU Usage</span>
|
||||
<span class="metric-value" id="cpu-usage">-</span>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<span class="metric-label">Uptime</span>
|
||||
<span class="metric-value" id="uptime">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status Indicators -->
|
||||
<div class="status-section">
|
||||
<h2>System Status</h2>
|
||||
<div class="status-indicators">
|
||||
<div class="status-item" id="status-api">
|
||||
<span class="status-label">API Service</span>
|
||||
<span class="status-badge">Checking...</span>
|
||||
</div>
|
||||
<div class="status-item" id="status-database">
|
||||
<span class="status-label">Database</span>
|
||||
<span class="status-badge">Checking...</span>
|
||||
</div>
|
||||
<div class="status-item" id="status-cache">
|
||||
<span class="status-label">Cache</span>
|
||||
<span class="status-badge">Checking...</span>
|
||||
</div>
|
||||
<div class="status-item" id="status-blockchain">
|
||||
<span class="status-label">Blockchain</span>
|
||||
<span class="status-badge">Checking...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="status-section">
|
||||
<h2>Active Alerts</h2>
|
||||
<div class="status-indicators" id="alert-indicators">
|
||||
<div class="status-item">
|
||||
<span class="status-label">Alert State</span>
|
||||
<span class="status-badge">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Auto-refresh metrics every 30 seconds
|
||||
let refreshInterval;
|
||||
const METRICS_ENDPOINT = '/v1/metrics';
|
||||
const HEALTH_ENDPOINT = '/v1/health';
|
||||
|
||||
function refreshMetrics() {
|
||||
// Update timestamp
|
||||
document.getElementById('last-updated').textContent = new Date().toLocaleTimeString();
|
||||
|
||||
fetchMetrics();
|
||||
checkServiceStatus();
|
||||
}
|
||||
|
||||
async function fetchMetrics() {
|
||||
try {
|
||||
const response = await fetch(METRICS_ENDPOINT, { method: 'GET', cache: 'no-cache' });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Metrics request failed with status ${response.status}`);
|
||||
}
|
||||
const metrics = await response.json();
|
||||
|
||||
// Update UI
|
||||
document.getElementById('api-requests').textContent = metrics.api_requests.toLocaleString();
|
||||
document.getElementById('api-errors').textContent = metrics.api_errors.toLocaleString();
|
||||
document.getElementById('error-rate').textContent = Number(metrics.error_rate_percent).toFixed(2) + '%';
|
||||
document.getElementById('avg-response-time').textContent = Number(metrics.avg_response_time_ms).toFixed(2) + 'ms';
|
||||
document.getElementById('db-queries').textContent = metrics.database_queries.toLocaleString();
|
||||
document.getElementById('db-errors').textContent = metrics.database_errors.toLocaleString();
|
||||
document.getElementById('active-connections').textContent = metrics.active_connections;
|
||||
document.getElementById('cache-hits').textContent = metrics.cache_hits.toLocaleString();
|
||||
document.getElementById('cache-misses').textContent = metrics.cache_misses.toLocaleString();
|
||||
document.getElementById('cache-hit-rate').textContent = Number(metrics.cache_hit_rate_percent).toFixed(2) + '%';
|
||||
document.getElementById('memory-usage').textContent = Number(metrics.memory_usage_mb).toFixed(2) + ' MB';
|
||||
document.getElementById('cpu-usage').textContent = Number(metrics.cpu_usage_percent).toFixed(2) + '%';
|
||||
document.getElementById('uptime').textContent = metrics.uptime_formatted;
|
||||
|
||||
resetMetricClasses();
|
||||
setMetricColor('error-rate', metrics.error_rate_percent, 1, 5);
|
||||
setMetricColor('avg-response-time', metrics.avg_response_time_ms, 500, 1000);
|
||||
setMetricColor('cache-hit-rate', metrics.cache_hit_rate_percent, 70, 85, true);
|
||||
setMetricColor('memory-usage', (metrics.alerts?.memory_usage?.value || 0), 75, 90);
|
||||
renderAlerts(metrics.alerts || {});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch metrics:', error);
|
||||
document.getElementById('alert-indicators').innerHTML = `
|
||||
<div class="status-item">
|
||||
<span class="status-label">Alert State</span>
|
||||
<span class="status-badge error">Metrics Unavailable</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
async function checkServiceStatus() {
|
||||
const services = [
|
||||
{ id: 'status-api', url: HEALTH_ENDPOINT },
|
||||
{ id: 'status-database', url: HEALTH_ENDPOINT },
|
||||
{ id: 'status-cache', url: HEALTH_ENDPOINT },
|
||||
{ id: 'status-blockchain', url: 'http://localhost:8006/v1/health' }
|
||||
];
|
||||
|
||||
for (const service of services) {
|
||||
try {
|
||||
const response = await fetch(service.url, { method: 'GET', cache: 'no-cache' });
|
||||
const badge = document.querySelector(`#${service.id} .status-badge`);
|
||||
|
||||
if (response.ok) {
|
||||
badge.textContent = 'Online';
|
||||
badge.className = 'status-badge success';
|
||||
} else {
|
||||
badge.textContent = 'Degraded';
|
||||
badge.className = 'status-badge warning';
|
||||
}
|
||||
} catch (error) {
|
||||
const badge = document.querySelector(`#${service.id} .status-badge`);
|
||||
badge.textContent = 'Offline';
|
||||
badge.className = 'status-badge error';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderAlerts(alerts) {
|
||||
const container = document.getElementById('alert-indicators');
|
||||
const entries = Object.entries(alerts);
|
||||
const triggeredAlerts = entries.filter(([, alert]) => alert.triggered);
|
||||
|
||||
if (entries.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="status-item">
|
||||
<span class="status-label">Alert State</span>
|
||||
<span class="status-badge warning">No Alert Data</span>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (triggeredAlerts.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="status-item">
|
||||
<span class="status-label">Alert State</span>
|
||||
<span class="status-badge success">All Clear</span>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = triggeredAlerts.map(([name, alert]) => `
|
||||
<div class="status-item">
|
||||
<span class="status-label">${formatAlertName(name)}</span>
|
||||
<span class="status-badge error">Critical (${alert.value} / ${alert.threshold})</span>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function formatAlertName(name) {
|
||||
return name.replaceAll('_', ' ').replace(/\b\w/g, (char) => char.toUpperCase());
|
||||
}
|
||||
|
||||
function resetMetricClasses() {
|
||||
document.querySelectorAll('.metric-value').forEach((element) => {
|
||||
element.classList.remove('success', 'warning', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function setMetricColor(elementId, value, warningThreshold, errorThreshold, invert = false) {
|
||||
const element = document.getElementById(elementId);
|
||||
const numValue = parseFloat(value);
|
||||
|
||||
if (invert) {
|
||||
// Higher is better (e.g., cache hit rate)
|
||||
if (numValue >= errorThreshold) {
|
||||
element.classList.add('success');
|
||||
} else if (numValue >= warningThreshold) {
|
||||
element.classList.add('warning');
|
||||
} else {
|
||||
element.classList.add('error');
|
||||
}
|
||||
} else {
|
||||
// Lower is better (e.g., error rate)
|
||||
if (numValue <= warningThreshold) {
|
||||
element.classList.add('success');
|
||||
} else if (numValue <= errorThreshold) {
|
||||
element.classList.add('warning');
|
||||
} else {
|
||||
element.classList.add('error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
refreshMetrics();
|
||||
refreshInterval = setInterval(refreshMetrics, 30000); // Refresh every 30 seconds
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user