BREAKING CHANGE(smartmetrics): add system-wide metrics collection, Prometheus gauges, and normalized CPU reporting
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user