mirror of
https://github.com/mendableai/firecrawl.git
synced 2024-11-16 11:42:24 +08:00
Update system-monitor.ts
This commit is contained in:
parent
a40fb3b062
commit
1f1afeaac4
|
@ -1,10 +1,16 @@
|
|||
import si from 'systeminformation';
|
||||
import { Mutex } from "async-mutex";
|
||||
import os from 'os';
|
||||
import fs from 'fs';
|
||||
import { Logger } from '../lib/logger';
|
||||
|
||||
const IS_KUBERNETES = process.env.IS_KUBERNETES === "true";
|
||||
|
||||
const MAX_CPU = process.env.MAX_CPU ? parseFloat(process.env.MAX_CPU) : 0.8;
|
||||
const MAX_RAM = process.env.MAX_RAM ? parseFloat(process.env.MAX_RAM) : 0.8;
|
||||
const CACHE_DURATION = process.env.SYS_INFO_MAX_CACHE_DURATION ? parseFloat(process.env.SYS_INFO_MAX_CACHE_DURATION) : 150;
|
||||
|
||||
|
||||
class SystemMonitor {
|
||||
private static instance: SystemMonitor;
|
||||
private static instanceMutex = new Mutex();
|
||||
|
@ -13,6 +19,10 @@ class SystemMonitor {
|
|||
private memoryUsageCache: number | null = null;
|
||||
private lastCpuCheck: number = 0;
|
||||
private lastMemoryCheck: number = 0;
|
||||
|
||||
// Variables for CPU usage calculation
|
||||
private previousCpuUsage: number = 0;
|
||||
private previousTime: number = Date.now();
|
||||
|
||||
private constructor() {}
|
||||
|
||||
|
@ -31,6 +41,50 @@ class SystemMonitor {
|
|||
}
|
||||
|
||||
private async checkMemoryUsage() {
|
||||
if (IS_KUBERNETES) {
|
||||
return this._checkMemoryUsageKubernetes();
|
||||
}
|
||||
return this._checkMemoryUsage();
|
||||
}
|
||||
|
||||
|
||||
private readMemoryCurrent(): number {
|
||||
const data = fs.readFileSync('/sys/fs/cgroup/memory.current', 'utf8');
|
||||
return parseInt(data.trim(), 10);
|
||||
}
|
||||
|
||||
private readMemoryMax(): number {
|
||||
const data = fs.readFileSync('/sys/fs/cgroup/memory.max', 'utf8').trim();
|
||||
if (data === 'max') {
|
||||
return Infinity;
|
||||
}
|
||||
return parseInt(data, 10);
|
||||
}
|
||||
private async _checkMemoryUsageKubernetes() {
|
||||
try {
|
||||
const currentMemoryUsage = this.readMemoryCurrent();
|
||||
const memoryLimit = this.readMemoryMax();
|
||||
|
||||
let memoryUsagePercentage: number;
|
||||
|
||||
if (memoryLimit === Infinity) {
|
||||
// No memory limit set; use total system memory
|
||||
const totalMemory = os.totalmem();
|
||||
memoryUsagePercentage = currentMemoryUsage / totalMemory;
|
||||
} else {
|
||||
memoryUsagePercentage = currentMemoryUsage / memoryLimit;
|
||||
}
|
||||
|
||||
// console.log("Memory usage:", memoryUsagePercentage);
|
||||
|
||||
return memoryUsagePercentage;
|
||||
} catch (error) {
|
||||
Logger.error(`Error calculating memory usage: ${error}`);
|
||||
return 0; // Fallback to 0% usage
|
||||
}
|
||||
}
|
||||
|
||||
private async _checkMemoryUsage() {
|
||||
const now = Date.now();
|
||||
if (this.memoryUsageCache !== null && (now - this.lastMemoryCheck) < CACHE_DURATION) {
|
||||
return this.memoryUsageCache;
|
||||
|
@ -49,6 +103,94 @@ class SystemMonitor {
|
|||
}
|
||||
|
||||
private async checkCpuUsage() {
|
||||
if (IS_KUBERNETES) {
|
||||
return this._checkCpuUsageKubernetes();
|
||||
}
|
||||
return this._checkCpuUsage();
|
||||
}
|
||||
private readCpuUsage(): number {
|
||||
const data = fs.readFileSync('/sys/fs/cgroup/cpu.stat', 'utf8');
|
||||
const match = data.match(/^usage_usec (\d+)$/m);
|
||||
if (match) {
|
||||
return parseInt(match[1], 10);
|
||||
}
|
||||
throw new Error('Could not read usage_usec from cpu.stat');
|
||||
}
|
||||
|
||||
|
||||
private getNumberOfCPUs(): number {
|
||||
let cpus: number[] = [];
|
||||
try {
|
||||
const cpusetPath = '/sys/fs/cgroup/cpuset.cpus.effective';
|
||||
const data = fs.readFileSync(cpusetPath, 'utf8').trim();
|
||||
|
||||
if (!data) {
|
||||
throw new Error(`${cpusetPath} is empty.`);
|
||||
}
|
||||
|
||||
cpus = this.parseCpuList(data);
|
||||
|
||||
if (cpus.length === 0) {
|
||||
throw new Error('No CPUs found in cpuset.cpus.effective');
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.warn(`Unable to read cpuset.cpus.effective, defaulting to OS CPUs: ${error}`);
|
||||
cpus = os.cpus().map((cpu, index) => index);
|
||||
}
|
||||
return cpus.length;
|
||||
}
|
||||
|
||||
|
||||
private parseCpuList(cpuList: string): number[] {
|
||||
const ranges = cpuList.split(',');
|
||||
const cpus: number[] = [];
|
||||
ranges.forEach((range) => {
|
||||
const [startStr, endStr] = range.split('-');
|
||||
const start = parseInt(startStr, 10);
|
||||
const end = endStr !== undefined ? parseInt(endStr, 10) : start;
|
||||
for (let i = start; i <= end; i++) {
|
||||
cpus.push(i);
|
||||
}
|
||||
});
|
||||
return cpus;
|
||||
}
|
||||
private async _checkCpuUsageKubernetes() {
|
||||
try {
|
||||
const usage = this.readCpuUsage(); // In microseconds (µs)
|
||||
const now = Date.now();
|
||||
|
||||
// Check if it's the first run
|
||||
if (this.previousCpuUsage === 0) {
|
||||
// Initialize previous values
|
||||
this.previousCpuUsage = usage;
|
||||
this.previousTime = now;
|
||||
// Return 0% CPU usage on first run
|
||||
return 0;
|
||||
}
|
||||
|
||||
const deltaUsage = usage - this.previousCpuUsage; // In µs
|
||||
const deltaTime = (now - this.previousTime) * 1000; // Convert ms to µs
|
||||
|
||||
const numCPUs = this.getNumberOfCPUs(); // Get the number of CPUs
|
||||
|
||||
// Calculate the CPU usage percentage and normalize by the number of CPUs
|
||||
const cpuUsagePercentage = (deltaUsage / deltaTime) / numCPUs;
|
||||
|
||||
// Update previous values
|
||||
this.previousCpuUsage = usage;
|
||||
this.previousTime = now;
|
||||
|
||||
// console.log("CPU usage:", cpuUsagePercentage);
|
||||
|
||||
return cpuUsagePercentage;
|
||||
} catch (error) {
|
||||
Logger.error(`Error calculating CPU usage: ${error}`);
|
||||
return 0; // Fallback to 0% usage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async _checkCpuUsage() {
|
||||
const now = Date.now();
|
||||
if (this.cpuUsageCache !== null && (now - this.lastCpuCheck) < CACHE_DURATION) {
|
||||
return this.cpuUsageCache;
|
||||
|
|
Loading…
Reference in New Issue
Block a user