bodhi-node-profiler
Version:
A lightweight, zero-configuration performance profiler for Node.js applications with real-time dashboard
103 lines (93 loc) • 3.36 kB
JavaScript
let charts = {
cpu: null,
memory: null,
eventLoop: null
};
const createChart = (ctx, label) => {
return new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: label,
data: [],
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
},
options: {
responsive: true,
animation: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
};
const initializeCharts = () => {
charts.cpu = createChart(document.getElementById('cpuChart').getContext('2d'), 'CPU %');
charts.memory = createChart(document.getElementById('memoryChart').getContext('2d'), 'Memory Usage (MB)');
charts.eventLoop = createChart(document.getElementById('eventLoopChart').getContext('2d'), 'Delay (ms)');
};
const updateCharts = (metrics) => {
const timestamp = new Date().toLocaleTimeString();
// Update CPU Chart
charts.cpu.data.labels.push(timestamp);
charts.cpu.data.datasets[0].data.push(metrics.currentStats.cpu.usage);
if (charts.cpu.data.labels.length > 20) {
charts.cpu.data.labels.shift();
charts.cpu.data.datasets[0].data.shift();
}
charts.cpu.update();
// Update Memory Chart
const memoryUsageMB = metrics.currentStats.memory.heapUsed / 1024 / 1024;
charts.memory.data.labels.push(timestamp);
charts.memory.data.datasets[0].data.push(memoryUsageMB);
if (charts.memory.data.labels.length > 20) {
charts.memory.data.labels.shift();
charts.memory.data.datasets[0].data.shift();
}
charts.memory.update();
// Update Event Loop Chart
charts.eventLoop.data.labels.push(timestamp);
charts.eventLoop.data.datasets[0].data.push(metrics.currentStats.eventLoopDelay);
if (charts.eventLoop.data.labels.length > 20) {
charts.eventLoop.data.labels.shift();
charts.eventLoop.data.datasets[0].data.shift();
}
charts.eventLoop.update();
};
const updateApiTable = (metrics) => {
const tableBody = document.getElementById('apiTable');
tableBody.innerHTML = '';
metrics.metrics.apiResponses.forEach((duration, route) => {
const row = document.createElement('tr');
row.innerHTML = `
<td class="px-6 py-4">${route}</td>
<td class="px-6 py-4">${duration.toFixed(2)}ms</td>
<td class="px-6 py-4">
<span class="px-2 py-1 rounded-full text-sm ${duration > 1000 ? 'bg-red-100 text-red-800' : 'bg-green-100 text-green-800'}">
${duration > 1000 ? 'Slow' : 'Good'}
</span>
</td>
`;
tableBody.appendChild(row);
});
};
const fetchMetrics = async () => {
try {
const response = await fetch('/api/metrics');
const metrics = await response.json();
updateCharts(metrics);
updateApiTable(metrics);
} catch (error) {
console.error('Error fetching metrics:', error);
}
};
// Initialize
document.addEventListener('DOMContentLoaded', () => {
initializeCharts();
setInterval(fetchMetrics, 1000);
});