import { monitoring as monitoringApi, services as servicesApi } from '../api.js';
import { icons } from '../icons.js';
const RANGES = [
{ value: '-1h', label: '1 ora' },
{ value: '-6h', label: '6 ore' },
{ value: '-24h', label: '24 ore' },
{ value: '-7d', label: '7 giorni' },
];
const METRICS = [
{ value: 'cpu_percent', label: 'CPU %', color: '#6366f1' },
{ value: 'memory_percent', label: 'RAM %', color: '#8b5cf6' },
{ value: 'network_rx', label: 'Network RX', color: '#10b981' },
{ value: 'network_tx', label: 'Network TX', color: '#f59e0b' },
];
export function renderMonitoring(container) {
let stats = {};
let selectedService = null;
let chartRange = '-1h';
let chartMetric = 'cpu_percent';
let chart = null;
let interval;
container.innerHTML = `
`;
async function loadInitial() {
try {
const st = await monitoringApi.realtime();
stats = st;
renderStats();
} catch {}
}
async function pollStats() {
try { stats = await monitoringApi.realtime(); renderStats(); } catch {}
}
function formatBytes(bytes) {
if (!bytes) return '0 B';
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;
}
function renderStats() {
const grid = document.getElementById('stats-grid');
const entries = Object.entries(stats);
if (entries.length === 0) {
grid.innerHTML = '';
document.getElementById('empty-msg').innerHTML = `${icons.activity(48)}
Nessun servizio attivo
I dati di monitoring saranno visibili quando almeno un servizio sarà in esecuzione
`;
document.getElementById('empty-msg').classList.remove('hidden');
return;
}
document.getElementById('empty-msg').classList.add('hidden');
grid.innerHTML = entries.map(([name, s]) => `
${icons.cpu(12)} CPU
${s?.cpu_percent?.toFixed(1) || '0'}%
${icons.hardDrive(12)} RAM
${formatBytes(s?.memory_usage)}
/ ${formatBytes(s?.memory_limit)}
${icons.wifi(12)} Net RX
${formatBytes(s?.network_rx)}
${icons.wifi(12)} Net TX
${formatBytes(s?.network_tx)}
`).join('');
grid.querySelectorAll('.metric-card').forEach(card => {
card.onclick = () => {
selectedService = card.dataset.svc;
renderStats();
renderChart();
};
});
}
async function renderChart() {
if (!selectedService) { document.getElementById('chart-section').classList.add('hidden'); return; }
const section = document.getElementById('chart-section');
section.classList.remove('hidden');
section.innerHTML = `
${METRICS.map(m => ``).join('')}
`;
section.querySelectorAll('[data-range]').forEach(b => {
b.onclick = () => { chartRange = b.dataset.range; renderChart(); };
});
section.querySelectorAll('[data-metric]').forEach(b => {
b.onclick = () => { chartMetric = b.dataset.metric; renderChart(); };
});
await loadChartData();
}
async function loadChartData() {
try {
const result = await monitoringApi.history(selectedService, chartRange, chartMetric);
const labels = result.map(d => new Date(d.time).toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit' }));
const values = result.map(d => Math.round(d.value * 100) / 100);
const currentMetric = METRICS.find(m => m.value === chartMetric);
if (chart) chart.destroy();
const canvas = document.getElementById('monitoring-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
// Use Chart.js if available
if (typeof Chart !== 'undefined') {
chart = new Chart(ctx, {
type: 'line',
data: {
labels,
datasets: [{
data: values,
borderColor: currentMetric.color,
backgroundColor: currentMetric.color + '30',
fill: true,
tension: 0.3,
pointRadius: 0,
pointHitRadius: 10,
borderWidth: 2,
}],
},
options: {
responsive: true, maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
x: { ticks: { color: '#6b7280', font: { size: 11 } }, grid: { color: 'rgba(255,255,255,0.05)' } },
y: {
min: chartMetric.includes('percent') ? 0 : undefined,
max: chartMetric.includes('percent') ? 100 : undefined,
ticks: { color: '#6b7280', font: { size: 11 } },
grid: { color: 'rgba(255,255,255,0.05)' },
},
},
},
});
} else {
document.getElementById('chart-area').innerHTML = `Chart.js non caricato. Aggiungi chart.min.js nella cartella lib/
`;
}
} catch (err) {
document.getElementById('chart-area').innerHTML = ``;
}
}
loadInitial();
interval = setInterval(pollStats, 5000);
return () => {
clearInterval(interval);
if (chart) chart.destroy();
};
}