|
@@ -23,11 +23,16 @@ export interface SystemMetrics {
|
|
|
// Keep legacy alias so the Gateway compiles without changes
|
|
// Keep legacy alias so the Gateway compiles without changes
|
|
|
export type MonitorPayload = SystemMetrics;
|
|
export type MonitorPayload = SystemMetrics;
|
|
|
|
|
|
|
|
-// Command-based signatures — checked against p.command to avoid node.exe collisions
|
|
|
|
|
-const SERVICE_SIGNATURES: Record<string, string> = {
|
|
|
|
|
- nestjs: 'main.js',
|
|
|
|
|
- n8n: 'n8n',
|
|
|
|
|
- ollama: 'ollama',
|
|
|
|
|
|
|
+const normalizeCommand = (cmd: string | null | undefined): string => {
|
|
|
|
|
+ if (!cmd) return '';
|
|
|
|
|
+ return cmd.toLowerCase().replace(/\\/g, '/').trim();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// Matcher functions — nestjs uses PID identity; others use .some() over signature arrays for resilience
|
|
|
|
|
+const SERVICE_MATCHERS: Record<string, (p: si.Systeminformation.ProcessesProcessData) => boolean> = {
|
|
|
|
|
+ nestjs: (p) => p.pid === process.pid,
|
|
|
|
|
+ n8n: (p) => { const cmd = normalizeCommand(p.command); return ['n8n', 'n8n.exe', 'n8n-desktop'].some(sig => cmd.includes(sig)); },
|
|
|
|
|
+ ollama: (p) => { const cmd = normalizeCommand(p.command); return ['ollama', 'ollama_llama_server'].some(sig => cmd.includes(sig)); },
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
@Injectable()
|
|
@Injectable()
|
|
@@ -103,15 +108,12 @@ export class SurveillanceService implements OnModuleInit, OnModuleDestroy {
|
|
|
): ServiceStatus[] {
|
|
): ServiceStatus[] {
|
|
|
const ACTIVE_CPU_THRESHOLD = 1.0;
|
|
const ACTIVE_CPU_THRESHOLD = 1.0;
|
|
|
|
|
|
|
|
- const statuses = Object.entries(SERVICE_SIGNATURES).map(([serviceName, signature]) => {
|
|
|
|
|
|
|
+ const statuses = Object.entries(SERVICE_MATCHERS).map(([serviceName, matcher]) => {
|
|
|
if (processList.length === 0) {
|
|
if (processList.length === 0) {
|
|
|
return { service: serviceName, pid: null, status: 'OFFLINE' as ServiceStatusType, cpu: 0, memory: 0 };
|
|
return { service: serviceName, pid: null, status: 'OFFLINE' as ServiceStatusType, cpu: 0, memory: 0 };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Single-pass filter by command — avoids node.exe collisions from name-only matching
|
|
|
|
|
- const matches = processList.filter((p) =>
|
|
|
|
|
- (p.command ?? '').toLowerCase().includes(signature.toLowerCase()),
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ const matches = processList.filter(matcher);
|
|
|
|
|
|
|
|
if (matches.length === 0) {
|
|
if (matches.length === 0) {
|
|
|
return { service: serviceName, pid: null, status: 'OFFLINE' as ServiceStatusType, cpu: 0, memory: 0 };
|
|
return { service: serviceName, pid: null, status: 'OFFLINE' as ServiceStatusType, cpu: 0, memory: 0 };
|