BREAKING CHANGE(smartmetrics): add system-wide metrics collection, Prometheus gauges, and normalized CPU reporting

This commit is contained in:
2026-02-19 10:10:58 +00:00
parent 32d75804c0
commit b99d2cc04b
7 changed files with 210 additions and 14 deletions

View File

@@ -12,6 +12,12 @@ export class SmartMetrics {
private cpuPercentageGauge: plugins.prom.Gauge;
private memoryPercentageGauge: plugins.prom.Gauge;
private memoryUsageBytesGauge: plugins.prom.Gauge;
private systemCpuPercentGauge: plugins.prom.Gauge;
private systemMemUsedPercentGauge: plugins.prom.Gauge;
private systemMemUsedBytesGauge: plugins.prom.Gauge;
private systemLoadAvg1Gauge: plugins.prom.Gauge;
private systemLoadAvg5Gauge: plugins.prom.Gauge;
private systemLoadAvg15Gauge: plugins.prom.Gauge;
// HTTP server for Prometheus endpoint
private prometheusServer?: plugins.http.Server;
@@ -39,6 +45,42 @@ export class SmartMetrics {
help: 'Current memory usage in bytes',
registers: [this.registry]
});
this.systemCpuPercentGauge = new plugins.prom.Gauge({
name: 'smartmetrics_system_cpu_percent',
help: 'System-wide CPU usage percentage',
registers: [this.registry]
});
this.systemMemUsedPercentGauge = new plugins.prom.Gauge({
name: 'smartmetrics_system_memory_used_percent',
help: 'System-wide memory usage percentage',
registers: [this.registry]
});
this.systemMemUsedBytesGauge = new plugins.prom.Gauge({
name: 'smartmetrics_system_memory_used_bytes',
help: 'System-wide memory used in bytes',
registers: [this.registry]
});
this.systemLoadAvg1Gauge = new plugins.prom.Gauge({
name: 'smartmetrics_system_load_avg_1',
help: 'System 1-minute load average',
registers: [this.registry]
});
this.systemLoadAvg5Gauge = new plugins.prom.Gauge({
name: 'smartmetrics_system_load_avg_5',
help: 'System 5-minute load average',
registers: [this.registry]
});
this.systemLoadAvg15Gauge = new plugins.prom.Gauge({
name: 'smartmetrics_system_load_avg_15',
help: 'System 15-minute load average',
registers: [this.registry]
});
}
constructor(loggerArg: plugins.smartlog.Smartlog, sourceNameArg: string) {
@@ -115,17 +157,18 @@ export class SmartMetrics {
}
const stats = await plugins.pidusage.getPidUsage([process.pid, ...pids]);
// Aggregate normalized CPU (0-100% of total machine) across process tree
let cpuPercentage = 0;
for (const stat of Object.keys(stats)) {
if (!stats[stat as any]) continue;
cpuPercentage += stats[stat as any].cpu;
for (const stat of Object.values(stats)) {
if (!stat) continue;
cpuPercentage += stat.cpuNormalizedPercent;
}
let cpuUsageText = `${Math.round(cpuPercentage * 100) / 100} %`;
let memoryUsageBytes = 0;
for (const stat of Object.keys(stats)) {
if (!stats[stat as any]) continue;
memoryUsageBytes += stats[stat as any].memory;
for (const stat of Object.values(stats)) {
if (!stat) continue;
memoryUsageBytes += stat.memory;
}
let memoryPercentage =
@@ -134,6 +177,9 @@ export class SmartMetrics {
memoryUsageBytes
)} / ${this.formatBytes(this.maxMemoryMB * 1024 * 1024)}`;
// Get system-wide metrics
const systemUsage = await plugins.sysusage.getSystemUsage();
// Update Prometheus gauges with current values
if (this.cpuPercentageGauge) {
this.cpuPercentageGauge.set(cpuPercentage);
@@ -144,16 +190,32 @@ export class SmartMetrics {
if (this.memoryUsageBytesGauge) {
this.memoryUsageBytesGauge.set(memoryUsageBytes);
}
if (this.systemCpuPercentGauge) {
this.systemCpuPercentGauge.set(systemUsage.cpuPercent);
}
if (this.systemMemUsedPercentGauge) {
this.systemMemUsedPercentGauge.set(systemUsage.memUsedPercent);
}
if (this.systemMemUsedBytesGauge) {
this.systemMemUsedBytesGauge.set(systemUsage.memUsedBytes);
}
if (this.systemLoadAvg1Gauge) {
this.systemLoadAvg1Gauge.set(systemUsage.loadAvg1);
}
if (this.systemLoadAvg5Gauge) {
this.systemLoadAvg5Gauge.set(systemUsage.loadAvg5);
}
if (this.systemLoadAvg15Gauge) {
this.systemLoadAvg15Gauge.set(systemUsage.loadAvg15);
}
// Calculate Node.js metrics directly
const cpuUsage = process.cpuUsage();
const process_cpu_seconds_total = (cpuUsage.user + cpuUsage.system) / 1000000; // Convert from microseconds to seconds
const process_cpu_seconds_total = (cpuUsage.user + cpuUsage.system) / 1000000;
const heapStats = plugins.v8.getHeapStatistics();
const nodejs_heap_size_total_bytes = heapStats.total_heap_size;
// Note: Active handles and requests are internal Node.js metrics that require deprecated APIs
// We return 0 here, but the Prometheus default collectors will track the real values
const nodejs_active_handles_total = 0;
const nodejs_active_requests_total = 0;
@@ -167,6 +229,14 @@ export class SmartMetrics {
memoryPercentage,
memoryUsageBytes,
memoryUsageText,
systemCpuPercent: systemUsage.cpuPercent,
systemMemTotalBytes: systemUsage.memTotalBytes,
systemMemAvailableBytes: systemUsage.memAvailableBytes,
systemMemUsedBytes: systemUsage.memUsedBytes,
systemMemUsedPercent: systemUsage.memUsedPercent,
systemLoadAvg1: systemUsage.loadAvg1,
systemLoadAvg5: systemUsage.loadAvg5,
systemLoadAvg15: systemUsage.loadAvg15,
};
return returnMetrics;
}