VPS Monitoring
The Control Center collects and visualizes real-time VPS metrics using the systeminformation Node.js library, Socket.IO for live updates, and Recharts for visualization.
Metrics Collected
Collection Intervals
| Interval | Storage | Retention |
|---|---|---|
| 3 seconds | In-memory (pushed via Socket.IO) | Last 5 minutes |
| 60 seconds | SQLite MetricSnapshot table | 30 days |
Metric Categories
| Category | Metrics | Source |
|---|---|---|
| CPU | Usage percentage (per core + total), load average | systeminformation.currentLoad() |
| Memory | Used, free, total, swap used, swap total | systeminformation.mem() |
| Disk | Usage per mount point, read/write IOPS, available space | systeminformation.fsSize(), systeminformation.disksIO() |
| Network | Bandwidth in/out (bytes/sec), packet counts, interface stats | systeminformation.networkStats() |
Implementation
Metrics Collection Service
// apps/server/src/services/vps.service.ts
import si from 'systeminformation';
export const vpsService = {
async collectMetrics() {
const [cpu, memory, disk, network] = await Promise.all([
si.currentLoad(),
si.mem(),
si.fsSize(),
si.networkStats(),
]);
return {
cpu: {
total: cpu.currentLoad,
cores: cpu.cpus.map(c => c.load),
loadAvg: cpu.avgLoad,
},
memory: {
used: memory.used,
free: memory.free,
total: memory.total,
swapUsed: memory.swapused,
swapTotal: memory.swaptotal,
usagePercent: (memory.used / memory.total) * 100,
},
disk: disk.map(d => ({
mount: d.mount,
size: d.size,
used: d.used,
available: d.available,
usagePercent: d.use,
})),
network: network.map(n => ({
interface: n.iface,
rxBytes: n.rx_bytes,
txBytes: n.tx_bytes,
rxPerSec: n.rx_sec,
txPerSec: n.tx_sec,
})),
timestamp: new Date(),
};
},
};
Metrics Scheduler
// apps/server/src/services/metrics.service.ts
let collectionCount = 0;
// Collect every 3 seconds
setInterval(async () => {
const metrics = await vpsService.collectMetrics();
// Push to all connected Socket.IO clients
io.of('/metrics').emit('vps:metrics', metrics);
collectionCount++;
// Persist every 60 seconds (every 20th collection)
if (collectionCount % 20 === 0) {
await prisma.metricSnapshot.create({
data: {
cpu: metrics.cpu.total,
memory: JSON.stringify(metrics.memory),
disk: JSON.stringify(metrics.disk),
network: JSON.stringify(metrics.network),
timestamp: metrics.timestamp,
},
});
}
}, 3000);
Data Retention
// Clean up metrics older than 30 days (daily cron)
async function cleanOldMetrics() {
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
await prisma.metricSnapshot.deleteMany({
where: { timestamp: { lt: thirtyDaysAgo } },
});
}
Real-Time Delivery
Metrics are pushed to connected clients via the /metrics Socket.IO namespace:
// Server: emit metrics
io.of('/metrics').emit('vps:metrics', metrics);
// Client: receive and render
import { useEffect, useState } from 'react';
import { io } from 'socket.io-client';
function VPSMonitor() {
const [metrics, setMetrics] = useState(null);
useEffect(() => {
const socket = io('/metrics', {
auth: { token: getAccessToken() }, // JWT required
});
socket.on('vps:metrics', (data) => {
setMetrics(data);
});
return () => socket.disconnect();
}, []);
return <MetricsCharts data={metrics} />;
}
Dashboard Visualizations
| Chart | Data Source | Type |
|---|---|---|
| CPU Usage (real-time) | Live Socket.IO stream | Area chart with 5-minute window |
| Memory Usage | Live + historical | Gauge + time-series |
| Disk Usage | Per mount point | Donut chart per mount |
| Network I/O | Live bandwidth | Stacked area chart (in/out) |
| CPU History (30 days) | MetricSnapshot table | Time-series line chart |
| Memory History (30 days) | MetricSnapshot table | Time-series line chart |
Alert Thresholds
| Metric | Warning | Critical | Action |
|---|---|---|---|
| CPU | > 80% sustained (5 min) | > 95% sustained (2 min) | Notification |
| Memory | > 85% usage | > 95% usage | Notification |
| Disk | > 85% on any mount | > 95% on any mount | Notification |
| Network | Unusual spike (> 3x baseline) | - | Notification |
Alerts are created as Notification records and pushed via the /notifications Socket.IO namespace.
Cross-Reference
- Control Center Architecture -- overall CC architecture
- Docker Management -- container-level metrics
- Control Center Setup -- installation and configuration