This commit is contained in:
2026-02-19 09:46:46 +00:00
parent 767a40e01e
commit 7c3197455f
5 changed files with 36 additions and 29 deletions

View File

@@ -17,7 +17,7 @@ export class SmartMetrics {
private prometheusServer?: plugins.http.Server;
private prometheusPort?: number;
public async setup() {
public setup() {
const collectDefaultMetrics = plugins.promClient.collectDefaultMetrics;
this.registry = new plugins.promClient.Registry();
collectDefaultMetrics({ register: this.registry });
@@ -50,28 +50,32 @@ export class SmartMetrics {
}
private checkMemoryLimits() {
let heapStats = plugins.v8.getHeapStatistics();
let maxHeapSizeMB = heapStats.heap_size_limit / 1024 / 1024;
let totalSystemMemoryMB = plugins.os.totalmem() / 1024 / 1024;
const heapStats = plugins.v8.getHeapStatistics();
const maxHeapSizeMB = heapStats.heap_size_limit / 1024 / 1024;
const totalSystemMemoryMB = plugins.os.totalmem() / 1024 / 1024;
let dockerMemoryLimitMB = totalSystemMemoryMB;
// Try cgroup v2 first, then fall back to cgroup v1
try {
let dockerMemoryLimitBytes = plugins.fs.readFileSync(
'/sys/fs/cgroup/memory/memory.limit_in_bytes',
'utf8'
);
dockerMemoryLimitMB = parseInt(dockerMemoryLimitBytes, 10) / 1024 / 1024;
} catch (error) {
// Ignore - this will fail if not running in a Docker container
const cgroupV2 = plugins.fs.readFileSync('/sys/fs/cgroup/memory.max', 'utf8').trim();
if (cgroupV2 !== 'max') {
dockerMemoryLimitMB = parseInt(cgroupV2, 10) / 1024 / 1024;
}
} catch {
try {
const cgroupV1 = plugins.fs.readFileSync(
'/sys/fs/cgroup/memory/memory.limit_in_bytes',
'utf8'
).trim();
dockerMemoryLimitMB = parseInt(cgroupV1, 10) / 1024 / 1024;
} catch {
// Not running in a container — use system memory
}
}
// Set the maximum memory to the lower value between the Docker limit and the total system memory
// Pick the most restrictive limit
this.maxMemoryMB = Math.min(totalSystemMemoryMB, dockerMemoryLimitMB, maxHeapSizeMB);
// If the maximum old space size limit is greater than the maximum available memory, throw an error
if (maxHeapSizeMB > this.maxMemoryMB) {
throw new Error('Node.js process can use more memory than is available');
}
}
public start() {
@@ -104,7 +108,12 @@ export class SmartMetrics {
}
public async getMetrics() {
const pids = await plugins.pidtree(process.pid);
let pids: number[] = [];
try {
pids = await plugins.pidtree(process.pid);
} catch {
// pidtree can fail if process tree cannot be read
}
const stats = await plugins.pidusage([process.pid, ...pids]);
let cpuPercentage = 0;
@@ -126,8 +135,6 @@ export class SmartMetrics {
memoryUsageBytes
)} / ${this.formatBytes(this.maxMemoryMB * 1024 * 1024)}`;
console.log(`${cpuUsageText} ||| ${memoryUsageText} `);
// Update Prometheus gauges with current values
if (this.cpuPercentageGauge) {
this.cpuPercentageGauge.set(cpuPercentage);